`
cloudtech
  • 浏览: 4594307 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

一个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
#defineUUID32_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).*/
shorttm_year;/*Year(currentyearminus1900).*/
shorttm_yday;/*Dayofyear(0–365;January1=0).*/
longtm_fraction;/*Fractionlittlethan1second*/
}timestamp_t;

typedef
struct_uuid_t
{
unsigned
longdata1;
unsigned
shortdata2;
unsigned
shortdata3;
unsigned
chardata4[8];
}uuid_t;


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

/**
*GeneratesanewUUID.TheUUIDisatime-basedtime1UUID.
*Arandomper-processnodeidentifierisusedtoavoidkeepingglobal
*stateandmaintaininginter-processsynchronization.
*
*/
voiduuid_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)
*
*/
voiduuid_create_external(constchar*external,uuid_t*uuid);

/**
*Translateauuid_ttoauuidstring
*returnUUIDstring
*
*/
char*uuid_to_string(constuuid_t*uuid);

/**
*GettimestampfromaUUID
*
*/
voiduuid_to_timestamp(constuuid_t*uuid,timestamp_t*time);


/**
*ResurnadescriptionoftimestampNOTincludingfraction
*
*/
char*timestamp_to_string(consttimestamp_t*time);

/**
*ComparetwoUUID'slexically
*return
*-1u1islexicallybeforeu2
*0u1isequaltou2
*1u1islexicallyafteru2
*/
intuuid_compare(constuuid_t*u1,constuuid_t*u2);

/**
*ComparetwoUUID'stemporally
*return
*-1u1istemporallybeforeu2
*0u1isequaltou2
*1u1istemporallyafteru2
*/
intuuid_compare_time(constuuid_t*u1,constuuid_t*u2);


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

/*============================================================================*/
typedefunsigned
charuchar,byte,BYTE;

typedefunsigned
shortuint16,word_t,ushort;

typedefunsigned
intuint,uint32,dword_t,size_t;

typedefunsigned
longulong;

typedef__int64int64;
typedefunsigned__int64uint64,qword_t;


#ifndefBOOL
#defineBOOLint
#defineTRUE1
#defineFALSE0
#endif

#ifndefRESULT
#defineRESULTlong
#defineSUCCESS0
#defineERROR-1
#endif

#defineSIZE_BYTE1
#defineSIZE_SHORT2
#defineSIZE_INT4
#defineSIZE_FLT4
#defineSIZE_DBL8
#defineSIZE_WORD2
#defineSIZE_DWORD4
#defineSIZE_QWORD8
#defineSIZE_LINT8
#defineSIZE_INT648
#defineSIZE_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
intstate[4];/*state(ABCD)*/
unsigned
intcount[2];/*numberofbits,modulo2^64(lsbfirst)*/
unsigned
charbuffer[64];/*inputbuffer*/
}MD5_CTX;

voidMD5_init(MD5_CTX*);
voidMD5_update(MD5_CTX*,constunsignedchar*str,unsignedintlen);
voidMD5_fini(unsignedchar[16],MD5_CTX*);

char*MD5_sign(constunsignedchar*str,unsignedintlen);

#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"

#defineMD5STR_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.*/
#defineS117
#defineS1212
#defineS1317
#defineS1422
#defineS215
#defineS229
#defineS2314
#defineS2420
#defineS314
#defineS3211
#defineS3316
#defineS3423
#defineS416
#defineS4210
#defineS4315
#defineS4421

staticvoid_MD5Transform(unsignedint[4],constunsignedchar[64]);
staticvoid_Encode(unsignedchar*,unsignedint*,unsignedint);
staticvoid_Decode(unsignedint*,constunsignedchar*,unsignedint);

staticunsignedcharPADDING[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.*/
#defineF(x,y,z)(((x)&(y))|((~x)&(z)))
#defineG(x,y,z)(((x)&(z))|((y)&(~z)))
#defineH(x,y,z)((x)^(y)^(z))
#defineI(x,y,z)((y)^((x)|(~z)))

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

/*FF,GG,HH,andIItransformationsforrounds1,2,3,and4.
Rotationisseparatefromadditiontopreventrecomputation.
*/
#defineFF(a,b,c,d,x,s,ac){
(a)
+=F((b),(c),(d))+(x)+(unsignedint)(ac);
(a)
=ROTATE_LEFT((a),(s));
(a)
+=(b);
}
#defineGG(a,b,c,d,x,s,ac){
(a)
+=G((b),(c),(d))+(x)+(unsignedint)(ac);
(a)
=ROTATE_LEFT((a),(s));
(a)
+=(b);
}
#defineHH(a,b,c,d,x,s,ac){
(a)
+=H((b),(c),(d))+(x)+(unsignedint)(ac);
(a)
=ROTATE_LEFT((a),(s));
(a)
+=(b);
}
#defineII(a,b,c,d,x,s,ac){
(a)
+=I((b),(c),(d))+(x)+(unsignedint)(ac);
(a)
=ROTATE_LEFT((a),(s));
(a)
+=(b);
}

/*MD5initialization.BeginsanMD5operation,writinganewcontext.*/
voidMD5_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.
*/
voidMD5_update(MD5_CTX*context,constunsignedchar*input,unsignedintinputLen)
{
unsigned
inti,index,partLen;

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

/*Updatenumberofbits*/
if((context->count[0]+=((unsignedint)inputLen<<3))<((unsignedint)inputLen<<3))
context
->count[1]++;
context
->count[1]+=((unsignedint)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.*/
voidMD5_fini(unsignedchardigest[16],MD5_CTX*context)
{
unsigned
charbits[8];
unsigned
intindex,padLen;

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

/*Padoutto56mod64.*/
index
=(unsignedint)((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));
}

#pragmawarning(push)/*C4996*/
#pragmawarning(disable:4996)

char*MD5_sign(constunsignedchar*str,unsignedintlen)
{
inti;
MD5_CTXmd5;
staticcharmd5_str[MD5STR_LEN+1];
charhash[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);
}

returnmd5_str;
}

#pragmawarning(pop)/*C4996*/

/*MD5basictransformation.Transformsstatebasedonblock.*/
staticvoid_MD5Transform(unsignedintstate[4],constunsignedcharblock[64])
{
unsigned
inta=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.*/
staticvoid_Encode(unsignedchar*output,unsignedint*input,unsignedintlen)
{
unsigned
inti,j;

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

/*Decodesinput(unsignedchar)intooutput(unsignedint).Assumeslenisamultipleof4.*/
staticvoid_Decode(unsignedint*output,constunsignedchar*input,unsignedintlen)
{
unsigned
inti,j;

for(i=0,j=0;j<len;i++,j+=4){
output[i]
=((unsignedint)input[j])|(((unsignedint)input[j+1])<<8)|
(((unsigned
int)input[j+2])<<16)|(((unsignedint)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"


#defineMD5_LEN16
#defineUUID_LEN36

/*microsecondpersecond.1s=1000000us=1000000000ns*/
#defineNSec100_Per_Sec10000000
#defineUSec_Per_Sec1000000
#defineUSec_Per_MSec1000
#defineNSec_Since_1582((uint64)(0x01B21DD213814000))


/*========================================================================================
PrivateFunctions
========================================================================================
*/
staticBOOLisbigendian()
{
intc=1;
return(*((unsignedchar*)&c)==1)?FALSE:TRUE;
};

staticvoidswap_word(intsize_bytes,void*ptr_word)
{
inti;
unsigned
chartemp;
for(i=0;i<size_bytes/2;i++)
{
temp
=((unsignedchar*)ptr_word)[i];
((unsigned
char*)ptr_word)[i]=((unsignedchar*)ptr_word)[size_bytes-i-1];
((unsigned
char*)ptr_word)[size_bytes-i-1]=temp;
}
};

staticvoidwrite_word(unsignedchar*stream,word_tval)
{
memcpy(stream,
&val,2);
if(isbigendian())swap_word(2,stream);
};

staticvoidwrite_dword(unsignedchar*stream,dword_tval)
{
memcpy(stream,
&val,4);
if(isbigendian())swap_word(4,stream);
};

staticvoidread_word(constunsignedchar*stream,word_t*val)
{
memcpy(val,stream,
2);
if(isbigendian())swap_word(2,val);
};

staticvoidread_dword(constunsignedchar*stream,dword_t*val)
{
memcpy(val,stream,
4);
if(isbigendian())swap_word(4,val);
};

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


/*makeapseudorandomnumbelbasedoncurrenttime*/
staticintpseudo_rand()
{
#ifdef_USE_32BIT_TIME_T
assert(
0);
#endif

struct_timebtimebuf;

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

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

returnrand();
};


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

BOOLis_uuid_string(
constchar*uuid)
{
staticconstcharfmt[]="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
inti;
assert(uuid
!=NULL);
for(i=0;i<sizeof(fmt);i++)
if(fmt[i]=='x')
if(!is_xdigit(uuid[i]))
returnFALSE;
elseif(uuid[i]!=fmt[i])
returnFALSE;

returnTRUE;
}


/**
*internal
*ingroupuuid
*ThethreadsynchronizationlockusedtoguaranteeUUIDuniqueness
*forallthethreadsrunningwithinaprocess.
*/
voiduuid_create(uuid_t*u)
{
staticBOOLinitialized=FALSE;
staticint64timestamp;
staticuint32advance;
staticuint16clockseq;
staticuint16node_high;
staticuint32node_low;
int64time;
/*unitof100ns*/
uint16nowseq;
intr;

#ifdef_USE_32BIT_TIME_T
assert(
0);
#endif

struct_timebtv;

assert(u);

#pragmawarning(push)/*C4996*/
#pragmawarning(disable:4996)
_ftime64(
&tv);
#pragmawarning(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;
}
elseif(time<timestamp)
{
timestamp
=time;
advance
=0;
clockseq
++;
}
elseif(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);
returnuuid_to_string(&u);
}

char*uuid_to_string(constuuid_t*u)
{
staticcharuuid_str[UUID_LEN+1];
ushorta,b;
uint32c;
read_word(
&(u->data4[6]),&a);
read_word(
&(u->data4[4]),&b);
read_dword(
&(u->data4[0]),&c);

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

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

voiduuid_create_external(constchar*external,uuid_t*u)
{
MD5_CTXmd5;
unsigned
charuuid[16];

assert(external
!=NULL);

MD5_init(
&md5);
MD5_update(
&md5,namespace_uuid,sizeof(namespace_uuid));
MD5_update(
&md5,(unsignedchar*)external,(unsignedint)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
*
*/
voiduuid_to_timestamp(constuuid_t*u,timestamp_t*t)
{
int64time,t2,t3;
structtm*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;

#pragmawarning(push)/*C4996*/
#pragmawarning(disable:4996)
p
=_localtime64(&time);
#pragmawarning(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(consttimestamp_t*time)
{
structtmt;
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;

#pragmawarning(push)/*C4996*/
#pragmawarning(disable:4996)
returnasctime(&t);
#pragmawarning(pop)/*C4996*/
}



/**
*ComparetwoUUID'slexically
*return
*-1u1islexicallybeforeu2
*0u1isequaltou2
*1u1islexicallyafteru2
*/
intuuid_compare(constuuid_t*u1,constuuid_t*u2)
{
inti;

#defineCHECK_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]);

#undefCHECK_COMP

return0;
}

/**
*ComparetwoUUID'stemporally
*return
*-1u1istemporallybeforeu2
*0u1isequaltou2
*1u1istemporallyafteru2
*/
intuuid_compare_time(constuuid_t*u1,constuuid_t*u2)
{
#defineCHECK_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);

#undefCHECK_COMP

return0;
}

好了,到此,所有文件都列出来了,它们是: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"

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

sign
=MD5_sign("helloworld",(unsignedint)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));

return0;
}

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics