根據定義,UUID(Universally Unique IDentifier,也稱GUID)在時間和空間都是唯一的。為保證空間的唯一性,每個UUID使用了一個48位的值來記錄,一般是電腦的網卡地址。為保證時間上的唯一性,每個UUID具有一個60位的時間戳記(timestamp)。這個時間戳記表示自公元1582年(絕對不是1852,這是《COM技術內幕》,1999年3月第1版第89頁中的一個錯誤)10月15號00:00:00:00以來的時間,是以100納秒為單位的時間間隔。1納秒(ns)=10-9秒(s)。UUID演算法可以保證至大約公元3400年仍然唯一。UUID的C語言結構定義如下:
typedef struct _uuid_t
{
unsigned long data1;
unsigned short data2;
unsigned short data3;
unsigned char data4[8];
} uuid_t;
它的結構大小為16個位元組。即sizeof(uuid_t)==16為TRUE。寫成16進位字串的格式,一般為:
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
上面的字串形式,佔用36個字元,不包括結尾Null 字元’\0’。所以,要想容納一個UUID字串,必須聲明為一個char[36+1]的字元數組。
以軟體演算法實現UUID非常有現實意義。參考RFC4122文檔和其他一些開原始碼,我寫了一個WIN32下的UUID實現C語言程式——UUID32.c。程式符合RFC4122標準。程式不但實現建立UUID和UUID String,還可以對UUID進行字元和時間上的比較。還可以從UUID從提取時間戳記(精度到秒)。標頭檔uuid32.h定義如下:
/* uuid32.h
2007-09-15 Last created by cheungmine.
Partly rights reserved by cheungmine.
*/
#ifndef UUID32_H_INCLUDED
#define UUID32_H_INCLUDED
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <memory.h>
#include "cdatatype.h"
typedef struct _timestamp_t
{
BYTE tm_sec; /* Seconds after minute (0 – 59). */
BYTE tm_min; /* Minutes after hour (0 – 59). */
BYTE tm_hour; /* Hours after midnight (0 – 23). */
BYTE tm_mday; /* Day of month (1 – 31). */
BYTE tm_mon; /* Month (0 – 11; January = 0). */
BYTE tm_wday; /* Day of week (0 – 6; Sunday = 0). */
short tm_year; /* Year (current year minus 1900). */
short tm_yday; /* Day of year (0 – 365; January 1 = 0). */
long tm_fraction; /* Fraction little than 1 second */
} timestamp_t;
typedef struct _uuid_t
{
unsigned long data1;
unsigned short data2;
unsigned short data3;
unsigned char data4[8];
} uuid_t;
/**
* Checks whether the given string matches the UUID format.
* params:
* [in] uuid - the potential UUID string
* return
* TRUE if the given string is a UUID, FALSE otherwise
**/
BOOL is_uuid_string(const char *uuid);
/**
* Generates a new UUID. The UUID is a time-based time 1 UUID.
* A random per-process node identifier is used to avoid keeping global
* state and maintaining inter-process synchronization.
**/
void uuid_create(uuid_t* uuid);
/**
* Generates a new UUID string. The returned UUID is a time-based time 1 UUID.
* A random per-process node identifier is used to avoid keeping global
* state and maintaining inter-process synchronization.
* return UUID string (newly allocated)
**/
char *uuid_create_string(void);
/**
* Generates a name-based (type 3) UUID string from the given external
* identifier. The special namespace UUID is used as the namespace of
* the generated UUID.
* params
* [in] external - the external identifier
* return
* UUID string (newly allocated)
**/
void uuid_create_external(const char *external, uuid_t* uuid);
/**
* Translate a uuid_t to a uuid string
* return UUID string
**/
char *uuid_to_string(const uuid_t* uuid);
/**
* Get timestamp from a UUID
**/
void uuid_to_timestamp(const uuid_t* uuid, timestamp_t* time);
/**
* Resurn a description of timestamp NOT including fraction
**/
char* timestamp_to_string(const timestamp_t* time);
/**
* Compare two UUID's lexically
* return
* -1 u1 is lexically before u2
* 0 u1 is equal to u2
* 1 u1 is lexically after u2
*/
int uuid_compare(const uuid_t *u1, const uuid_t *u2);
/**
* Compare two UUID's temporally
* return
* -1 u1 is temporally before u2
* 0 u1 is equal to u2
* 1 u1 is temporally after u2
*/
int uuid_compare_time(const uuid_t *u1, const uuid_t *u2);
#endif /* UUID32_H_INCLUDED */