一个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*/
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__*/
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__*/
#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 );
}
}
*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 ;
}
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 ;
}
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 ;
}
以上代码保证正确。请放心使用!