库名 libuuid 下载地址https://sourceforge.net/projects/libuuid/
版本1.0.3
运行环境:mac

接口

uuid对外定义为一个无符号字符数组,这是一个压缩后的存储

typedef unsigned char uuid_t[16];

内部其实是一个结构体

struct uuid {
    uint32_t    time_low;
    uint16_t    time_mid;
    uint16_t    time_hi_and_version;
    uint16_t    clock_seq;
    uint8_t node[6];
};

time_low是一个32位整数,每8位转化成一个无符号字符,占了前面4位,然后是time_mid占2位,time_hi_and_version占2位,clock_seq占2位,最后node数组占6位,一共正好16位。

提供4个函数生成不同的uuid

  • uuid_generate_random 如果有随机设备则利用随机设备生产随机字符串流,否则利用glibc的伪随机函数生成,然后对clock_seq和time_hi_and_version做一些位操作(为什么?)
  • uuid_generate_time 和random一样生成随机字符串,然后对clock_seq,然后对clock_sql,time_mid和time_hi_and_version进行位操作
  • uuid_generate 根据系统是否提供/dev/random或/dev/urandom伪随机设备,来决定用random还是time构造uuid,linux系统一般提供
  • uuid_generate_time_safe 调用了uuid_generate_time_generic,内部使用uuid daemon生成uuid

几个函数获取uuid内部的属性:

  • uuid_time 获取基于时间的uuid的时间值
  • uuid_type 返回时间或随机
  • uuid_variant 返回平台

构造和打印uuid的函数:

  • uuid_unparse 把uuid buf解析成字符串
  • uuid_unparse_lower
  • uuid_unparse_upper
  • uuid_parse 把一个字符串解析成uuid

操作uuid的几个函数:

  • uuid_compare
  • uuid_clear
  • uuid_copy
  • uuid_is_null
    从名字就可以看出用途,后续给出源码中的test代码。

源码

接口

/* clear.c */
void uuid_clear(uuid_t uu);

/* compare.c */
int uuid_compare(const uuid_t uu1, const uuid_t uu2);

/* copy.c */
void uuid_copy(uuid_t dst, const uuid_t src);

/* gen_uuid.c */
void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);
void uuid_generate_time(uuid_t out);
int uuid_generate_time_safe(uuid_t out);

/* isnull.c */
int uuid_is_null(const uuid_t uu);

/* parse.c */
int uuid_parse(const char *in, uuid_t uu);

/* unparse.c */
void uuid_unparse(const uuid_t uu, char *out);
void uuid_unparse_lower(const uuid_t uu, char *out);
void uuid_unparse_upper(const uuid_t uu, char *out);

/* uuid_time.c */
time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
int uuid_type(const uuid_t uu);
int uuid_variant(const uuid_t uu);

源码中包含的test代码:

#include <stdio.h>
#include <stdlib.h>

#include "uuid.h"

static int test_uuid(const char * uuid, int isValid)
{
    static const char * validStr[2] = {"invalid", "valid"};
    uuid_t uuidBits;
    int parsedOk;

    parsedOk = uuid_parse(uuid, uuidBits) == 0;

    printf("%s is %s", uuid, validStr[isValid]);
    if (parsedOk != isValid) {
        printf(" but uuid_parse says %s\n", validStr[parsedOk]);
        return 1;
    }
    printf(", OK\n");
    return 0;
}

int
main(int argc ATTR((unused)) , char **argv ATTR((unused)))
{
    uuid_t      buf, tst;
    char        str[100];
    struct timeval  tv;
    time_t      time_reg;
    unsigned char   *cp;
    int i;
    int failed = 0;
    int type, variant;

    uuid_generate(buf);
    uuid_unparse(buf, str);
    printf("UUID generate = %s\n", str);
    printf("UUID: ");
    for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
        printf("%02x", *cp++);
    }
    printf("\n");
    type = uuid_type(buf);  variant = uuid_variant(buf);
    printf("UUID type = %d, UUID variant = %d\n", type, variant);
    if (variant != UUID_VARIANT_DCE) {
        printf("Incorrect UUID Variant; was expecting DCE!\n");
        failed++;
    }
    printf("\n");

    uuid_generate_random(buf);
    uuid_unparse(buf, str);
    printf("UUID random string = %s\n", str);
    printf("UUID: ");
    for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
        printf("%02x", *cp++);
    }
    printf("\n");
    type = uuid_type(buf);  variant = uuid_variant(buf);
    printf("UUID type = %d, UUID variant = %d\n", type, variant);
    if (variant != UUID_VARIANT_DCE) {
        printf("Incorrect UUID Variant; was expecting DCE!\n");
        failed++;
    }
    if (type != 4) {
        printf("Incorrect UUID type; was expecting "
               "4 (random type)!\n");
        failed++;
    }
    printf("\n");

    uuid_generate_time(buf);
    uuid_unparse(buf, str);
    printf("UUID string = %s\n", str);
    printf("UUID time: ");
    for (i=0, cp = (unsigned char *) &buf; i < 16; i++) {
        printf("%02x", *cp++);
    }
    printf("\n");
    type = uuid_type(buf);  variant = uuid_variant(buf);
    printf("UUID type = %d, UUID variant = %d\n", type, variant);
    if (variant != UUID_VARIANT_DCE) {
        printf("Incorrect UUID Variant; was expecting DCE!\n");
        failed++;
    }
    if (type != 1) {
        printf("Incorrect UUID type; was expecting "
               "1 (time-based type)!\\n");
        failed++;
    }    
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    time_reg = uuid_time(buf, &tv);
    printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec,
           ctime(&time_reg));
    uuid_parse(str, tst);
    if (!uuid_compare(buf, tst))
        printf("UUID parse and compare succeeded.\n");
    else {
        printf("UUID parse and compare failed!\n");
        failed++;
    }
    uuid_clear(tst);
    if (uuid_is_null(tst))
        printf("UUID clear and is null succeeded.\n");
    else {
        printf("UUID clear and is null failed!\n");
        failed++;
    }
    uuid_copy(buf, tst);
    if (!uuid_compare(buf, tst))
        printf("UUID copy and compare succeeded.\n");
    else {
        printf("UUID copy and compare failed!\n");
        failed++;
    }
    failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981b", 1);
    failed += test_uuid("84949CC5-4701-4A84-895B-354C584A981B", 1);
    failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981bc", 0);
    failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981", 0);
    failed += test_uuid("84949cc5x4701-4a84-895b-354c584a981b", 0);
    failed += test_uuid("84949cc504701-4a84-895b-354c584a981b", 0);
    failed += test_uuid("84949cc5-470104a84-895b-354c584a981b", 0);
    failed += test_uuid("84949cc5-4701-4a840895b-354c584a981b", 0);
    failed += test_uuid("84949cc5-4701-4a84-895b0354c584a981b", 0);
    failed += test_uuid("g4949cc5-4701-4a84-895b-354c584a981b", 0);
    failed += test_uuid("84949cc5-4701-4a84-895b-354c584a981g", 0);

    if (failed) {
        printf("%d failures.\n", failed);
        exit(1);
    }
    return 0;
}

运行命令:gcc test_uuid.c -I uuid.h .libs/libuuid.a
输出结果

UUID generate = dda308b8-92b7-425e-a0e9-5d3549b0a21d
UUID: dda308b892b7425ea0e95d3549b0a21d
UUID type = 4, UUID variant = 1

UUID random string = 5351ce55-18d0-4559-874e-db90d56a85a5
UUID: 5351ce5518d04559874edb90d56a85a5
UUID type = 4, UUID variant = 1

UUID string = dfb68e3a-39f6-11e7-ac17-555bc85646d4
UUID time: dfb68e3a39f611e7ac17555bc85646d4
UUID type = 1, UUID variant = 1
UUID time is: (1494911813, 611065): Tue May 16 13:16:53 2017

UUID parse and compare succeeded.
UUID clear and is null succeeded.
UUID copy and compare succeeded.
84949cc5-4701-4a84-895b-354c584a981b is valid, OK
84949CC5-4701-4A84-895B-354C584A981B is valid, OK
84949cc5-4701-4a84-895b-354c584a981bc is invalid, OK
84949cc5-4701-4a84-895b-354c584a981 is invalid, OK
84949cc5x4701-4a84-895b-354c584a981b is invalid, OK
84949cc504701-4a84-895b-354c584a981b is invalid, OK
84949cc5-470104a84-895b-354c584a981b is invalid, OK
84949cc5-4701-4a840895b-354c584a981b is invalid, OK
84949cc5-4701-4a84-895b0354c584a981b is invalid, OK
g4949cc5-4701-4a84-895b-354c584a981b is invalid, OK
84949cc5-4701-4a84-895b-354c584a981g is invalid, O

使用

./configure,make编译
简单代码示例:

#include 
#include "uuid.h"

using namespace std;

int main(int argc, char* argv[])
{
    uuid_t id1;
    char str[100];

    /* 生成uuid */
    uuid_generate(id1);
    uuid_unparse(id1, str);
    cout << str << endl;
    return 0;
}

编译:clang++ check.cpp -I uuid.h .libs/libuuid.a