一个UUID生成算法的C语言实现 --- WIN32版本

一个UUID生成算法的C语言实现——WIN32版本
cheungmine
2007-9-16
根据定义,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个字符,不包括结尾空字符’/0’。所以,要想容纳一个UUID字符串,必须声明为一个char[36+1]的字符数组。
以软件算法实现UUID非常有现实意义。参考RFC4122文档和其他一些开源代码,我写了一个WIN32下的UUID实现C语言程序——UUID32.c。程序符合RFC4122标准。程序不但实现创建UUID和UUID String,还可以对UUID进行字符和时间上的比较。还可以从UUID从提取时间戳(精度到秒)。头文件uuid32.h定义如下:
/* uuid32.h
2007-09-15Lastcreatedbycheungmine.
Partlyrightsreservedbycheungmine.
*/
#ifndefUUID32_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
{
BYTEtm_sec;
/* Secondsafterminute(0–59). */
BYTEtm_min;
/* Minutesafterhour(0–59). */
BYTEtm_hour;
/* Hoursaftermidnight(0–23). */
BYTEtm_mday;
/* Dayofmonth(1–31). */
BYTEtm_mon;
/* Month(0–11;January=0). */
BYTEtm_wday;
/* Dayofweek(0–6;Sunday=0). */
short tm_year; /* Year(currentyearminus1900). */
short tm_yday; /* Dayofyear(0–365;January1=0). */
long tm_fraction; /* Fractionlittlethan1second */
}timestamp_t;

typedef
struct _uuid_t
{
unsigned
long data1;
unsigned
short data2;
unsigned
short data3;
unsigned
char data4[ 8 ];
}uuid_t;


/* *
*CheckswhetherthegivenstringmatchestheUUIDformat.
*params:
*[in]uuid-thepotentialUUIDstring
*return
*TRUEifthegivenstringisaUUID,FALSEotherwise
*
*/
BOOLis_uuid_string(
const char * uuid);

/* *
*GeneratesanewUUID.TheUUIDisatime-basedtime1UUID.
*Arandomper-processnodeidentifierisusedtoavoidkeepingglobal
*stateandmaintaininginter-processsynchronization.
*
*/
void uuid_create(uuid_t * uuid);

/* *
*GeneratesanewUUIDstring.ThereturnedUUIDisatime-basedtime1UUID.
*Arandomper-processnodeidentifierisusedtoavoidkeepingglobal
*stateandmaintaininginter-processsynchronization.
*returnUUIDstring(newlyallocated)
*
*/
char * uuid_create_string( void );

/* *
*Generatesaname-based(type3)UUIDstringfromthegivenexternal
*identifier.ThespecialnamespaceUUIDisusedasthenamespaceof
*thegeneratedUUID.
*params
*[in]external-theexternalidentifier
*return
*UUIDstring(newlyallocated)
*
*/
void uuid_create_external( const char * external,uuid_t * uuid);

/* *
*Translateauuid_ttoauuidstring
*returnUUIDstring
*
*/
char * uuid_to_string( const uuid_t * uuid);

/* *
*GettimestampfromaUUID
*
*/
void uuid_to_timestamp( const uuid_t * uuid,timestamp_t * time);


/* *
*ResurnadescriptionoftimestampNOTincludingfraction
*
*/
char * timestamp_to_string( const timestamp_t * time);

/* *
*ComparetwoUUID'slexically
*return
*-1u1islexicallybeforeu2
*0u1isequaltou2
*1u1islexicallyafteru2
*/
int uuid_compare( const uuid_t * u1, const uuid_t * u2);

/* *
*ComparetwoUUID'stemporally
*return
*-1u1istemporallybeforeu2
*0u1isequaltou2
*1u1istemporallyafteru2
*/
int uuid_compare_time( const uuid_t * u1, const uuid_t * u2);


#endif /*UUID32_H_INCLUDED*/
其中,头文件"cdatatype.h"如下:
/* cdatatype.h
2008-09-15Lastcreatedbycheungmine.
Allrightsreservedbycheungmine.
*/
#ifndefCDATATYPE_H__
#define CDATATYPE_H__

/* ============================================================================ */
typedefunsigned
char uchar, byte ,BYTE;

typedefunsigned
short uint16,word_t, ushort ;

typedefunsigned
int uint ,uint32,dword_t,size_t;

typedefunsigned
long ulong ;

typedef__int64int64;
typedefunsigned__int64uint64,qword_t;


#ifndefBOOL
#define BOOLint
#define TRUE1
#define FALSE0
#endif

#ifndefRESULT
#define RESULTlong
#define SUCCESS0
#define ERROR-1
#endif

#define SIZE_BYTE1
#define SIZE_SHORT2
#define SIZE_INT4
#define SIZE_FLT4
#define SIZE_DBL8
#define SIZE_WORD2
#define SIZE_DWORD4
#define SIZE_QWORD8
#define SIZE_LINT8
#define SIZE_INT648
#define SIZE_UUID16

/* ============================================================================ */
#endif /*CDATATYPE_H__*/

MD5算法生成的文件有:md5.h和md5.c,分别罗列如下:

#ifndef_MD5_H__
#define _MD5_H__
/* MD5.H-headerfileforMD5C.C */

/* Copyright(C)1991-2,RSADataSecurity,Inc.Created1991.All
rightsreserved.

Licensetocopyandusethissoftwareisgrantedprovidedthatit
isidentifiedasthe"RSADataSecurity,Inc.MD5Message-Digest
Algorithm"inallmaterialmentioningorreferencingthissoftware
orthisfunction.

Licenseisalsograntedtomakeandusederivativeworksprovided
thatsuchworksareidentifiedas"derivedfromtheRSAData
Security,Inc.MD5Message-DigestAlgorithm"inallmaterial
mentioningorreferencingthederivedwork.

RSADataSecurity,Inc.makesnorepresentationsconcerningeither
themerchantabilityofthissoftwareorthesuitabilityofthis
softwareforanyparticularpurpose.Itisprovided"asis"
withoutexpressorimpliedwarrantyofanykind.

Thesenoticesmustberetainedinanycopiesofanypartofthis
documentationand/orsoftware.

2007-09-15Lastmodifiedbycheungmine.
*/

/* MD5context. */
typedef
struct {
unsigned
int state[ 4 ]; /* state(ABCD) */
unsigned
int count[ 2 ]; /* numberofbits,modulo2^64(lsbfirst) */
unsigned
char buffer[ 64 ]; /* inputbuffer */
}MD5_CTX;

void MD5_init(MD5_CTX * );
void MD5_update(MD5_CTX * , const unsigned char * str,unsigned int len);
void MD5_fini(unsigned char [ 16 ],MD5_CTX * );

char * MD5_sign( const unsigned char * str,unsigned int len);

#endif /*_MD5_H__*/

/*
*md5.c-Copyright1997LachlanRoche
*-Modifiedbycheungmine,2007-9-15
*/

#include
< stdio.h >
#include
< stdlib.h >
#include
< string .h >
#include
< memory.h >
#include
" md5.h "

#define MD5STR_LEN32


/* =====================================================================
TheremainingcodeisthereferenceMD5code(md5c.c)fromrfc1321
MD5C.C-RSADataSecurity,Inc.,MD5message-digestalgorithm

Copyright(C)1991-2,RSADataSecurity,Inc.Created1991.All
rightsreserved.

Licensetocopyandusethissoftwareisgrantedprovidedthatit
isidentifiedasthe"RSADataSecurity,Inc.MD5Message-Digest
Algorithm"inallmaterialmentioningorreferencingthissoftware
orthisfunction.

Licenseisalsograntedtomakeandusederivativeworksprovided
thatsuchworksareidentifiedas"derivedfromtheRSAData
Security,Inc.MD5Message-DigestAlgorithm"inallmaterial
mentioningorreferencingthederivedwork.

RSADataSecurity,Inc.makesnorepresentationsconcerningeither
themerchantabilityofthissoftwareorthesuitabilityofthis
softwareforanyparticularpurpose.Itisprovided"asis"
withoutexpressorimpliedwarrantyofanykind.

Thesenoticesmustberetainedinanycopiesofanypartofthis
documentationand/orsoftware.
=====================================================================
*/

/* Constantsfor_MD5Transformroutine. */
#define S117
#define S1212
#define S1317
#define S1422
#define S215
#define S229
#define S2314
#define S2420
#define S314
#define S3211
#define S3316
#define S3423
#define S416
#define S4210
#define S4315
#define S4421

static void _MD5Transform(unsigned int [ 4 ], const unsigned char [ 64 ]);
static void _Encode(unsigned char * ,unsigned int * ,unsigned int );
static void _Decode(unsigned int * , const unsigned char * ,unsigned int );

static unsigned char PADDING[ 64 ] = {
0x80 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
};

/* F,G,HandIarebasicMD5functions. */
#define F(x,y,z)(((x)&(y))|((~x)&(z)))
#define G(x,y,z)(((x)&(z))|((y)&(~z)))
#define H(x,y,z)((x)^(y)^(z))
#define I(x,y,z)((y)^((x)|(~z)))

/* ROTATE_LEFTrotatesxleftnbits. */
#define ROTATE_LEFT(x,n)(((x)<<(n))|((x)>>(32-(n))))

/* FF,GG,HH,andIItransformationsforrounds1,2,3,and4.
Rotationisseparatefromadditiontopreventrecomputation.
*/
#define FF(a,b,c,d,x,s,ac){
(a)
+= F((b),(c),(d)) + (x) + (unsigned int )(ac);
(a)
= ROTATE_LEFT((a),(s));
(a)
+= (b);
}
#define GG(a,b,c,d,x,s,ac){
(a)
+= G((b),(c),(d)) + (x) + (unsigned int )(ac);
(a)
= ROTATE_LEFT((a),(s));
(a)
+= (b);
}
#define HH(a,b,c,d,x,s,ac){
(a)
+= H((b),(c),(d)) + (x) + (unsigned int )(ac);
(a)
= ROTATE_LEFT((a),(s));
(a)
+= (b);
}
#define II(a,b,c,d,x,s,ac){
(a)
+= I((b),(c),(d)) + (x) + (unsigned int )(ac);
(a)
= ROTATE_LEFT((a),(s));
(a)
+= (b);
}

/* MD5initialization.BeginsanMD5operation,writinganewcontext. */
void MD5_init(MD5_CTX * context)
{
context
-> count[ 0 ] = context -> count[ 1 ] = 0 ;
/* Loadmagicinitializationconstants. */
context
-> state[ 0 ] = 0x67452301 ;
context
-> state[ 1 ] = 0xefcdab89 ;
context
-> state[ 2 ] = 0x98badcfe ;
context
-> state[ 3 ] = 0x10325476 ;
}

/* MD5blockupdateoperation.ContinuesanMD5message-digestoperation,
processinganothermessageblock,andupdatingthecontext.
*/
void MD5_update(MD5_CTX * context, const unsigned char * input,unsigned int inputLen)
{
unsigned
int i,index,partLen;

/* Computenumberofbytesmod64 */
index
= (unsigned int )((context -> count[ 0 ] >> 3 ) & 0x3F );

/* Updatenumberofbits */
if ((context -> count[ 0 ] += ((unsigned int )inputLen << 3 )) < ((unsigned int )inputLen << 3 ))
context
-> count[ 1 ] ++ ;
context
-> count[ 1 ] += ((unsigned int )inputLen >> 29 );

partLen
= 64 - index;

/* Transformasmanytimesaspossible. */
if (inputLen >= partLen){
memcpy((
void * ) & context -> buffer[index],( void * )input,partLen);
_MD5Transform(context
-> state,context -> buffer);

for (i = partLen;i + 63 < inputLen;i += 64 )
_MD5Transform(context
-> state, & input[i]);

index
= 0 ;
}
else
i
= 0 ;

/* Bufferremaininginput */
memcpy((
void * ) & context -> buffer[index],( void * ) & input[i],inputLen - i);
}

/* MD5finalization.EndsanMD5message-digestoperation,writingthemessagedigestandzeroizingthecontext. */
void MD5_fini(unsigned char digest[ 16 ],MD5_CTX * context)
{
unsigned
char bits[ 8 ];
unsigned
int index,padLen;

/* Savenumberofbits */
_Encode(bits,context
-> count, 8 );

/* Padoutto56mod64. */
index
= (unsigned int )((context -> count[ 0 ] >> 3 ) & 0x3f );
padLen
= (index < 56 ) ? ( 56 - index):( 120 - index);
MD5_update(context,PADDING,padLen);

/* Appendlength(beforepadding) */
MD5_update(context,bits,
8 );

/* Storestateindigest */
_Encode(digest,context
-> state, 16 );

/* Zeroizesensitiveinformation. */
memset((
void * )context, 0 , sizeof ( * context));
}

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)

char * MD5_sign( const unsigned char * str,unsigned int len)
{
int i;
MD5_CTXmd5;
static char md5_str[MD5STR_LEN + 1 ];
char hash[ 16 ],tmp[ 3 ];
md5_str[
0 ] = 0 ;

MD5_init(
& md5);
MD5_update(
& md5,str,len);
MD5_fini(hash,
& md5);

for (i = 0 ;i < 16 ;i ++ )
{
_itoa((unsigned
char )hash[i],tmp, 16 );

if (tmp[ 1 ] == 0 ){
tmp[
2 ] = 0 ;tmp[ 1 ] = tmp[ 0 ];tmp[ 0 ] = ' 0 ' ;
}
strcat(md5_str,tmp);
}

return md5_str;
}

#pragma warning(pop)/*C4996*/

/* MD5basictransformation.Transformsstatebasedonblock. */
static void _MD5Transform(unsigned int state[ 4 ], const unsigned char block[ 64 ])
{
unsigned
int a = state[ 0 ],
b
= state[ 1 ],
c
= state[ 2 ],
d
= state[ 3 ],
x[
16 ];

_Decode(x,block,
64 );

/* Round1 */
FF(a,b,c,d,x[
0 ],S11, 0xd76aa478 ); /* 1 */
FF(d,a,b,c,x[
1 ],S12, 0xe8c7b756 ); /* 2 */
FF(c,d,a,b,x[
2 ],S13, 0x242070db ); /* 3 */
FF(b,c,d,a,x[
3 ],S14, 0xc1bdceee ); /* 4 */
FF(a,b,c,d,x[
4 ],S11, 0xf57c0faf ); /* 5 */
FF(d,a,b,c,x[
5 ],S12, 0x4787c62a ); /* 6 */
FF(c,d,a,b,x[
6 ],S13, 0xa8304613 ); /* 7 */
FF(b,c,d,a,x[
7 ],S14, 0xfd469501 ); /* 8 */
FF(a,b,c,d,x[
8 ],S11, 0x698098d8 ); /* 9 */
FF(d,a,b,c,x[
9 ],S12, 0x8b44f7af ); /* 10 */
FF(c,d,a,b,x[
10 ],S13, 0xffff5bb1 ); /* 11 */
FF(b,c,d,a,x[
11 ],S14, 0x895cd7be ); /* 12 */
FF(a,b,c,d,x[
12 ],S11, 0x6b901122 ); /* 13 */
FF(d,a,b,c,x[
13 ],S12, 0xfd987193 ); /* 14 */
FF(c,d,a,b,x[
14 ],S13, 0xa679438e ); /* 15 */
FF(b,c,d,a,x[
15 ],S14, 0x49b40821 ); /* 16 */

/* Round2 */
GG(a,b,c,d,x[
1 ],S21, 0xf61e2562 ); /* 17 */
GG(d,a,b,c,x[
6 ],S22, 0xc040b340 ); /* 18 */
GG(c,d,a,b,x[
11 ],S23, 0x265e5a51 ); /* 19 */
GG(b,c,d,a,x[
0 ],S24, 0xe9b6c7aa ); /* 20 */
GG(a,b,c,d,x[
5 ],S21, 0xd62f105d ); /* 21 */
GG(d,a,b,c,x[
10 ],S22, 0x2441453 ); /* 22 */
GG(c,d,a,b,x[
15 ],S23, 0xd8a1e681 ); /* 23 */
GG(b,c,d,a,x[
4 ],S24, 0xe7d3fbc8 ); /* 24 */
GG(a,b,c,d,x[
9 ],S21, 0x21e1cde6 ); /* 25 */
GG(d,a,b,c,x[
14 ],S22, 0xc33707d6 ); /* 26 */
GG(c,d,a,b,x[
3 ],S23, 0xf4d50d87 ); /* 27 */
GG(b,c,d,a,x[
8 ],S24, 0x455a14ed ); /* 28 */
GG(a,b,c,d,x[
13 ],S21, 0xa9e3e905 ); /* 29 */
GG(d,a,b,c,x[
2 ],S22, 0xfcefa3f8 ); /* 30 */
GG(c,d,a,b,x[
7 ],S23, 0x676f02d9 ); /* 31 */
GG(b,c,d,a,x[
12 ],S24, 0x8d2a4c8a ); /* 32 */

/* Round3 */
HH(a,b,c,d,x[
5 ],S31, 0xfffa3942 ); /* 33 */
HH(d,a,b,c,x[
8 ],S32, 0x8771f681 ); /* 34 */
HH(c,d,a,b,x[
11 ],S33, 0x6d9d6122 ); /* 35 */
HH(b,c,d,a,x[
14 ],S34, 0xfde5380c ); /* 36 */
HH(a,b,c,d,x[
1 ],S31, 0xa4beea44 ); /* 37 */
HH(d,a,b,c,x[
4 ],S32, 0x4bdecfa9 ); /* 38 */
HH(c,d,a,b,x[
7 ],S33, 0xf6bb4b60 ); /* 39 */
HH(b,c,d,a,x[
10 ],S34, 0xbebfbc70 ); /* 40 */
HH(a,b,c,d,x[
13 ],S31, 0x289b7ec6 ); /* 41 */
HH(d,a,b,c,x[
0 ],S32, 0xeaa127fa ); /* 42 */
HH(c,d,a,b,x[
3 ],S33, 0xd4ef3085 ); /* 43 */
HH(b,c,d,a,x[
6 ],S34, 0x4881d05 ); /* 44 */
HH(a,b,c,d,x[
9 ],S31, 0xd9d4d039 ); /* 45 */
HH(d,a,b,c,x[
12 ],S32, 0xe6db99e5 ); /* 46 */
HH(c,d,a,b,x[
15 ],S33, 0x1fa27cf8 ); /* 47 */
HH(b,c,d,a,x[
2 ],S34, 0xc4ac5665 ); /* 48 */

/* Round4 */
II(a,b,c,d,x[
0 ],S41, 0xf4292244 ); /* 49 */
II(d,a,b,c,x[
7 ],S42, 0x432aff97 ); /* 50 */
II(c,d,a,b,x[
14 ],S43, 0xab9423a7 ); /* 51 */
II(b,c,d,a,x[
5 ],S44, 0xfc93a039 ); /* 52 */
II(a,b,c,d,x[
12 ],S41, 0x655b59c3 ); /* 53 */
II(d,a,b,c,x[
3 ],S42, 0x8f0ccc92 ); /* 54 */
II(c,d,a,b,x[
10 ],S43, 0xffeff47d ); /* 55 */
II(b,c,d,a,x[
1 ],S44, 0x85845dd1 ); /* 56 */
II(a,b,c,d,x[
8 ],S41, 0x6fa87e4f ); /* 57 */
II(d,a,b,c,x[
15 ],S42, 0xfe2ce6e0 ); /* 58 */
II(c,d,a,b,x[
6 ],S43, 0xa3014314 ); /* 59 */
II(b,c,d,a,x[
13 ],S44, 0x4e0811a1 ); /* 60 */
II(a,b,c,d,x[
4 ],S41, 0xf7537e82 ); /* 61 */
II(d,a,b,c,x[
11 ],S42, 0xbd3af235 ); /* 62 */
II(c,d,a,b,x[
2 ],S43, 0x2ad7d2bb ); /* 63 */
II(b,c,d,a,x[
9 ],S44, 0xeb86d391 ); /* 64 */

state[
0 ] += a;
state[
1 ] += b;
state[
2 ] += c;
state[
3 ] += d;

/* Zeroizesensitiveinformation. */
memset((
void * )x, 0 , sizeof (x));
}

/* Encodesinput(unsignedint)intooutput(unsignedchar).Assumeslenisamultipleof4. */
static void _Encode(unsigned char * output,unsigned int * input,unsigned int len)
{
unsigned
int i,j;

for (i = 0 ,j = 0 ;j < len;i ++ ,j += 4 ){
output[j]
= (unsigned char )(input[i] & 0xff );
output[j
+ 1 ] = (unsigned char )((input[i] >> 8 ) & 0xff );
output[j
+ 2 ] = (unsigned char )((input[i] >> 16 ) & 0xff );
output[j
+ 3 ] = (unsigned char )((input[i] >> 24 ) & 0xff );
}
}

/* Decodesinput(unsignedchar)intooutput(unsignedint).Assumeslenisamultipleof4. */
static void _Decode(unsigned int * output, const unsigned char * input,unsigned int len)
{
unsigned
int i,j;

for (i = 0 ,j = 0 ;j < len;i ++ ,j += 4 ){
output[i]
= ((unsigned int )input[j]) | (((unsigned int )input[j + 1 ]) << 8 ) |
(((unsigned
int )input[j + 2 ]) << 16 ) | (((unsigned int )input[j + 3 ]) << 24 );
}
}

uuid32.c文件如下:

/* uuid32.c
2007-09-15Lastcreatedbycheungmine.
Partlyrightsreservedbycheungmine.
*/

#include
< stdio.h >
#include
< string .h >

#include
< time.h >
#include
< sys / types.h >
#include
< sys / timeb.h >

#include
" uuid32.h "
#include
" md5.h "


#define MD5_LEN16
#define UUID_LEN36

/* microsecondpersecond.1s=1000000us=1000000000ns */
#define NSec100_Per_Sec10000000
#define USec_Per_Sec1000000
#define USec_Per_MSec1000
#define NSec_Since_1582((uint64)(0x01B21DD213814000))


/* ========================================================================================
PrivateFunctions
========================================================================================
*/
static BOOLisbigendian()
{
int c = 1 ;
return ( * ((unsigned char * ) & c) == 1 ) ? FALSE:TRUE;
};

static void swap_word( int size_bytes, void * ptr_word)
{
int i;
unsigned
char temp;
for (i = 0 ;i < size_bytes / 2 ;i ++ )
{
temp
= ((unsigned char * )ptr_word)[i];
((unsigned
char * )ptr_word)[i] = ((unsigned char * )ptr_word)[size_bytes - i - 1 ];
((unsigned
char * )ptr_word)[size_bytes - i - 1 ] = temp;
}
};

static void write_word(unsigned char * stream,word_tval)
{
memcpy(stream,
& val, 2 );
if (isbigendian())swap_word( 2 ,stream);
};

static void write_dword(unsigned char * stream,dword_tval)
{
memcpy(stream,
& val, 4 );
if (isbigendian())swap_word( 4 ,stream);
};

static void read_word( const unsigned char * stream,word_t * val)
{
memcpy(val,stream,
2 );
if (isbigendian())swap_word( 2 ,val);
};

static void read_dword( const unsigned char * stream,dword_t * val)
{
memcpy(val,stream,
4 );
if (isbigendian())swap_word( 4 ,val);
};

static BOOLis_xdigit( char c)
{
/* isxdigitreturnsanon-zerovalueifcisahexadecimaldigit(A–F,a–f,or0–9). */
return ((c >= ' A ' && c <= ' F ' ) || (c >= ' a ' && c <= ' f ' ) || (c >= ' 0 ' && c <= ' 9 ' )) ? TRUE:FALSE;
};


/* makeapseudorandomnumbelbasedoncurrenttime */
static int pseudo_rand()
{
#ifdef_USE_32BIT_TIME_T
assert(
0 );
#endif

struct _timebtimebuf;

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)
_ftime64(
& timebuf);
#pragma warning(pop)/*C4996*/

srand((uint32)((((uint32)timebuf.time
& 0xFFFF ) + (uint32)timebuf.millitm) ^ (uint32)timebuf.millitm));

return rand();
};


/* ========================================================================================
PublicFunctions
========================================================================================
*/

BOOLis_uuid_string(
const char * uuid)
{
static const char fmt[] = " xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx " ;
int i;
assert(uuid
!= NULL);
for (i = 0 ;i < sizeof (fmt);i ++ )
if (fmt[i] == ' x ' )
if ( ! is_xdigit(uuid[i]))
return FALSE;
else if (uuid[i] != fmt[i])
return FALSE;

return TRUE;
}


/* *
*internal
*ingroupuuid
*ThethreadsynchronizationlockusedtoguaranteeUUIDuniqueness
*forallthethreadsrunningwithinaprocess.
*/
void uuid_create(uuid_t * u)
{
static BOOLinitialized = FALSE;
static int64timestamp;
static uint32advance;
static uint16clockseq;
static uint16node_high;
static uint32node_low;
int64time;
/* unitof100ns */
uint16nowseq;
int r;

#ifdef_USE_32BIT_TIME_T
assert(
0 );
#endif

struct _timebtv;

assert(u);

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)
_ftime64(
& tv);
#pragma warning(pop)/*C4996*/

/* timeiscounterof100nstimeintervalsinceOct.15,1582(NOT1852) */
time
= ((uint64)tv.time) * USec_Per_Sec + ((uint64)tv.millitm * USec_Per_MSec);
time
= time * 10 + NSec_Since_1582;

if ( ! initialized)
{
timestamp
= time;
advance
= 0 ;

r
= pseudo_rand();

clockseq
= r >> 16 ;
node_high
= r | 0x0100 ;

node_low
= pseudo_rand();

initialized
= TRUE;
}
else if (time < timestamp)
{
timestamp
= time;
advance
= 0 ;
clockseq
++ ;
}
else if (time == timestamp)
{
advance
++ ;
time
+= advance;
}
else
{
timestamp
= time;
advance
= 0 ;
}
nowseq
= clockseq;

assert(u);
u
-> data1 = (dword_t)time;
u
-> data2 = (word_t)((time >> 32 ) & 0xffff );
u
-> data3 = (word_t)(((time >> 48 ) & 0x0ffff ) | 0x1000 );
write_word(
& (u -> data4[ 6 ]),(word_t)((nowseq & 0x3fff ) | 0x8000 ));
write_word(
& (u -> data4[ 4 ]),(word_t)(node_high));
write_dword(
& (u -> data4[ 0 ]),(dword_t)(node_low));
}

/* *
*internal
*ingroupuuid
*ThethreadsynchronizationlockusedtoguaranteeUUIDuniqueness
*forallthethreadsrunningwithinaprocess.
*/
char * uuid_create_string( void )
{
uuid_tu;
uuid_create(
& u);
return uuid_to_string( & u);
}

char * uuid_to_string( const uuid_t * u)
{
static char uuid_str[UUID_LEN + 1 ];
ushort a,b;
uint32c;
read_word(
& (u -> data4[ 6 ]), & a);
read_word(
& (u -> data4[ 4 ]), & b);
read_dword(
& (u -> data4[ 0 ]), & c);

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)
sprintf(uuid_str,
" %08lx-%04x-%04x-%04x-%04x%08lx " ,
u
-> data1,
u
-> data2,
u
-> data3,
a,b,c);
#pragma warning(pop)/*C4996*/
return uuid_str;
}

/* *
*internal
*ingroupuuid
*ThepredefinednamespaceUUID.Expressedinbinaryformat
*toavoidunnecessaryconversionwhengeneratingnamebasedUUIDs.
*/
static const unsigned char namespace_uuid[] = {
0x9c , 0xfb , 0xd9 , 0x1f , 0x11 , 0x72 , 0x4a , 0xf6 ,
0xbd , 0xcb , 0x9f , 0x34 , 0xe4 , 0x6f , 0xa0 , 0xfb
};

void uuid_create_external( const char * external,uuid_t * u)
{
MD5_CTXmd5;
unsigned
char uuid[ 16 ];

assert(external
!= NULL);

MD5_init(
& md5);
MD5_update(
& md5,namespace_uuid, sizeof (namespace_uuid));
MD5_update(
& md5,(unsigned char * )external,(unsigned int )strlen(external));
MD5_fini(uuid,
& md5);

u
-> data1 = (dword_t)(uuid[ 0 ] << 24 | uuid[ 1 ] << 16 | uuid[ 2 ] << 8 | uuid[ 3 ]);
u
-> data2 = (word_t)(uuid[ 4 ] << 8 | uuid[ 5 ]);
u
-> data3 = (word_t)(((uuid[ 6 ] & 0x0f ) | 0x30 ) << 8 | uuid[ 7 ]);

/* BYTE6-7 */
write_word(
& (u -> data4[ 6 ]),(word_t)(((uuid[ 8 ] & 0x3f ) | 0x80 ) << 8 | uuid[ 9 ]));
/* BYTE4-5 */
write_word(
& (u -> data4[ 4 ]),(word_t)(uuid[ 10 ] << 8 | uuid[ 11 ]));
/* BYTE0-3 */
write_dword(
& (u -> data4[ 0 ]),(dword_t)(uuid[ 12 ] << 24 | uuid[ 13 ] << 16 | uuid[ 14 ] << 8 | uuid[ 15 ]));
}

/* *
*GettimestampfromaUUID
*
*/
void uuid_to_timestamp( const uuid_t * u,timestamp_t * t)
{
int64time,t2,t3;
struct tm * p;
assert(u);

t2
= u -> data2;
t3
= u -> data3;

time
= u -> data1 + (t2 << 32 ) + ((t3 & 0x0fff ) << 48 ); /* 100ns */
time
-= NSec_Since_1582;

t
-> tm_fraction = ( long )(time % NSec100_Per_Sec);

time
/= 10 ;
time
/= USec_Per_Sec;

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)
p
= _localtime64( & time);
#pragma warning(pop)/*C4996*/

t
-> tm_hour = p -> tm_hour;
t
-> tm_mday = p -> tm_mday;
t
-> tm_min = p -> tm_min;
t
-> tm_mon = p -> tm_mon;
t
-> tm_sec = p -> tm_sec;
t
-> tm_wday = p -> tm_wday;
t
-> tm_yday = p -> tm_yday;
t
-> tm_year = p -> tm_year;
}

char * timestamp_to_string( const timestamp_t * time)
{
struct tmt;
t.tm_hour
= time -> tm_hour;
t.tm_mday
= time -> tm_mday;
t.tm_min
= time -> tm_min;
t.tm_mon
= time -> tm_mon;
t.tm_sec
= time -> tm_sec;
t.tm_wday
= time -> tm_wday;
t.tm_yday
= time -> tm_yday;
t.tm_year
= time -> tm_year;

#pragma warning(push)/*C4996*/
#pragma warning(disable:4996)
return asctime( & t);
#pragma warning(pop)/*C4996*/
}



/* *
*ComparetwoUUID'slexically
*return
*-1u1islexicallybeforeu2
*0u1isequaltou2
*1u1islexicallyafteru2
*/
int uuid_compare( const uuid_t * u1, const uuid_t * u2)
{
int i;

#define CHECK_COMP(f1,f2)if((f1)!=(f2))return((f1)<(f2)?-1:1);

CHECK_COMP(u1
-> data1,u2 -> data1);
CHECK_COMP(u1
-> data2,u2 -> data2);
CHECK_COMP(u1
-> data3,u2 -> data3);

for (i = 0 ;i < 8 ;i ++ )
CHECK_COMP(u1
-> data4[i],u1 -> data4[i]);

#undef CHECK_COMP

return 0 ;
}

/* *
*ComparetwoUUID'stemporally
*return
*-1u1istemporallybeforeu2
*0u1isequaltou2
*1u1istemporallyafteru2
*/
int uuid_compare_time( const uuid_t * u1, const uuid_t * u2)
{
#define CHECK_COMP(f1,f2)if((f1)!=(f2))return((f1)<(f2)?-1:1);

CHECK_COMP(u1
-> data1,u2 -> data1);
CHECK_COMP(u1
-> data2,u2 -> data2);
CHECK_COMP(u1
-> data3,u2 -> data3);

#undef CHECK_COMP

return 0 ;
}

好了,到此,所有文件都列出来了,它们是:cdatatype.h、md5.h、uuid32.h、md5.c和uuid32.c。

最后是测试代码:

/* uuidgen.c
2007-09-15Lastcreatedbycheungmine.
Allrightsreservedbycheungmine.
Capplication
*/
#include
< stdio.h >
#include
< stdlib.h >
#include
< string .h >

#include
" md5.h "
#include
" uuid32.h "

int main()
{
char * sign, * uid;
uuid_tu,v,x;
timestamp_tt;

sign
= MD5_sign( " helloworld " ,(unsigned int )strlen( " helloworld " ));
printf(
" md5stringdigit:%s " ,sign);

uuid_create(
& u);
uid
= uuid_to_string( & u);
printf(
" uuidUtostring:{%s} " ,uid);

uuid_create(
& v);
uid
= uuid_to_string( & v);
printf(
" uuidVtostring:{%s} " ,uid);

printf(
" uuidcompareUwithVlexically:%d " ,uuid_compare( & u, & v));

printf(
" uuidcompareVwithUtemporally:%d " ,uuid_compare_time( & v, & u));


uid
= uuid_create_string();
printf(
" newuuidstring:{%s} " ,uid);

uuid_create_external(
" cheungmine " , & x);
uid
= uuid_to_string( & x);
printf(
" newexternaluuidtostring:{%s} " ,uid);

uuid_to_timestamp(
& u, & t);
printf(
" %s " ,timestamp_to_string( & t));

return 0 ;
}

以上代码保证正确。请放心使用!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值