zoukankan      html  css  js  c++  java
  • boost uuid

    uuid:
     uuid库是一个小的使用工具,可以表示和生成UUID
     UUID是University Unique Identifier的缩写,它是一个128位的数字(16字节),不需要有一个中央认证机构就可以创建全国唯一的标示符。别名:GUID
     uuid位于名字空间boost::uuisd,没有集中的头文件,把功能分散在了若干小文件中,因此为了使用uuid组件,需要包含数个头文件,即:
    #include <boost/uuid/uuid.hpp>
    #include <boost/uuid/uuid_generators.hpp>
    #include <boost/uuid/uuid_io.hpp>
    using namespace boost::uuids;

    uuid还全面支持比较操作和流输入输出,两个uuid值的比较是基于字典序的,分别使用了标准算法std
    ::equal()和std::lexicographical_compare().

    用法:
     uuid是一个很小的类,它特意被设计为没有构造函数,可以像POD数据类型一样使用.
     uuid内部使用一个16字节的数组data作为UUID值的存储,这个数组是public的,因此可以任意访问,比如拷贝或者赋值。基于data数组,uuid提供了begin()和end()的迭代器支持,可以像一个容器一样操作UUID值的每个字节。成员函数size()和静态成员函数static_size()可以获得UUID的长度,是一个固定值,大小总为16,元素类型为unsigned char的容器。
    示例:
    #include <iostream>
    #include <vector>
    #include <assert.h>
    #include <boost/uuid/uuid.hpp>
    #include <boost/uuid/uuid_generators.hpp>
    #include <boost/uuid/uuid_io.hpp>
    using namespace boost::uuids;
    using namespace std;
    int main()
    {
     uuid u;
     assert(uuid::static_size() == 16);
     assert(u.size() == 16);
     vector<unsigned char> v(16, 7);
     //使用标准拷贝算法
     std::copy(v.begin(), v.end(), u.begin());
     assert(u.data[0] == u.data[1] && u.data[15] == 7);  //数组方式访问
     cout<<u<<endl;
     std::fill_n(u.data + 10, 6, 8); //标准算法fill_n直接操纵数组
     cout<<u<<endl;
     system("pause");
     return 0;
    }

     uuid内部定义的枚举类型variant_type标识了UUID的变体号,表示了UUID的布局类型,成员函数variant()可以获得这个UUID的变体号.
     UUID的生成有不同的算法,这些算法使用枚举version_type来标识,version()函数可以获得UUID的算法版本,uuid类可以识别现在的有五种生成算法:
     【1】基于时间和MAC的算法(version_time_based);
     【2】分布计算环境算法(dce_security);
     【3】MD5摘要算法(version_name_based_md5);
     【4】随机数算法(version_random_number)based)
     【5】SHA1摘要算法(version_name_based_shal)
    在数量庞大的UUID中有一个特殊的全零值nil,它表示一个无效的UUID,成员函数is_nil()可以检测uuid是否是nil。
    示范:uuid用于表示UUID用法的代码如下:
    uuid u;
    std::fill_n(u.begin(), u.size(), 0xab);
    assert(!u.is_nil);
    assert(u.variant() == u.variant_rfc_4122); //4122变体类型
    assert(!u.version() == u.version_unknown); //生成算法未知
    cout<<u<<endl;
    std::memset(u.data, 0, 16);
    assert(u.is_nil());
    uuid u1,u2;
    std::file_n(u1.begin(), u1.size(), 0xab);
    std::file_n(u2.begin(), u2.size(), 0xa0);
    assert(u1 != u2 && u1>u2);
    u2.data[0] = 0xff; //u2的第一个字节改为0xff
    assert(u1 < u2);
    std::memset(u1.data, 0, 16);
    std::memset(u2.data, 0, 16);
    assert(u1 == u2);

    生成器:
     使用uuid提供的数组和迭代器接口,可以直接写出任意的UUID值,但因为不使用规定的算法,手工创建的UUID值很容易重复,这种方式只适合于从其他地方获得的原始UUID值导入到uuid对象中,如果要创建属于自己的UUID,需要使用UUID生成器。
     uuid库提供了四种生成器,分别是Nil生成器,字符串生成器,名字生成器和随机生成器,它们都是函数对象,重载了operator(),可以直接调用uuid对象.

    Nil生成器:
     Nil生成器是最简单的UUID生成器,只能生成一个无效的UUID值,它的存在只是为了方便地表示无效UUID。
     Nil生成器的类名是nil_generator,另外有一个内联函数nil_uuid(),相当于直接调用了Nil生成器。
    示范:
     uuid u = nil_generator()();//第一对圆括号与nil_generator()结合,结果是调用nil_generator的构造函数,生成一个临时对象,然后第二对圆括号是nil_generator对象的operator()操作符重载,就像是一个函数调用,产生了一个nil uuid对象.
     assert(u.is_nil);
     u = nil_uuid();
     assert(u.is_nil());

    字符串生成器:
     字符串生成器string_generator可以从一个字符串创建出uuid对象,字符串可以是C数组(NULL结尾),string,wstring,或者是一对迭代器指定的字符序列的区间。
     string_generator对字符串的格式有严格的要求,有两种格式是可接受的,一种是没有连字符的全16进制数字,另一种是使用连字符,但必须符合UUID的定义,在第5,7,9,11,字节前使用连字符,其他位置出现连字符都不允许。UUID字符串也可以使用花括号括起来,除了花括号不能出现16进制数以外的任何字符,否则会抛出runtime_error异常。
    示范string_generator用法的代码如下:
    string_generator sgen; //声明字符串生成器对象
    uuid u1 = sgen("0123456789abcdef0123456789abcdef");
    cout<<u1<<endl;
    uuid u2 = sgen("01234567-89ab-cdef-0123-456789abcdef");
    cout<<u2<<endl;
    uuid u3 = sgen(L"{01234567-89ab-cdef-0123-456789abcdef}");
    cout<<u3<<endl;

    名字生成器:
     名字生成器name_generator使用基于名字的SHA1摘要算法,它需要先指定一个基准UUID,然后使用字符串名字派生出基于这个UUID的一系列UUID,名字生成器的典型的应用场景是为一个组织内的所有成员创建UUID标识,只有基准UUID不变,那么相同的名字总会产生相同的UUID。
    示范:name_generator用法:
    //首先生成一个组织的UUID
    uuid www_xxx_com = string_generator()("{0123456789abcdef0123456789abcdef}");
    name_generator ngen(www_xxx_com);//构造名字生成器
    uuid u1 = ngen("mario");//为名字mario生成UUID
    assert(!u1.is_nil() && u1.version() == uuid::version_name_based_sha1);//version是sha1算法
    uuid u2 = ngen("link");//为名字link生成uuid
    cout<<u2<<endl;

    随机生成器:
     随机生成器采用随机数生成UUID,uuid库使用Boost库的另一个组件random作为随机数的发生源,它可以产生高质量的伪随机数,保证生成的随机UUID不会重复。
     随机生成器basic_random_generator是一个模板类,可以用模板参数指定要使用的随机数发生器,具有的随机数类可以参考random库,为了方便使用,uuid定义了一个常用的生成器random_generator,它使用mt19937作为随机数发生器。
    示范随机生成器用法的代码:
    random_generator rgen;//随机生成器
    uuid u = rgen();//生成一个随机的UUID
    assert(u.version() == uuid::version_random_number_based)
    cout<<u<<endl;

    增强的uuid类:
     uuid类为了追求效率而没有提供构造函数,要生成一个UUID值,必须要使用生成器,但有时候这个操作步骤显得有些麻烦,因此可以从uuid类派生一个可以自动产生uuid值的增强类,以简化uuid的使用。

     uuid_t,它是uuid的子类,具有uuid的全部能力,它内部定义了两个生成器的静态成员变量,分别用来产生随机uuid和字符串uuid,对应地也提供了两种重载形式的构造函数,对于Nil生成器,uuid_t使用带int参数的构造函数来调用实现,而名字生成器则使用了接受uuid和字符串参数的构造函数。
     uuid_t还实现了两个类型转换操作符重载,可以隐式地转换uuid对象,方便被应用在其他使用uuid类型的场景。

    uuid_t的全部实现代码:
    class uuid_t:pubilc uuid
    {
    private:
     static random_generator rgen; //随机生成器
     static string_generator sgen;//字符串生成器
    public:
     uuid_t(): uuid(rgen()){}//缺省构造函数,生成随机UUID
     uuid_t(int):uuid(nil_uuid()){}//0值的uuid构造函数
     uuid_t(const char*str):uuid(sgen(str)){}//字符串构造函数
     uuid_t(const uuid&u, const char* str)://名字生成器构造函数
      uuid(name_generator(u)(str)){}
     explicit uuid_t(const uuid& u):uuid(u){}拷贝构造函数
     operator uuid()//转换到uuid类型
     { return static_cast<uuid&>(*this);}
     operator uuid() const //常函数,转换到const uuid类型
     { return static_cast<const uuid&>(*this);}
    };

    random_generator uuid_t::rgen;//静态成员变量的定义
    string_generator uuid_t::sgen;

     由于uuid_t类封装了uuid的所有生成器,故它比uuid用起来更加方便容易,例如:
    uuid_t u0 =0;
    assert(u0.is_nil());;
    uuid_t u1,u2;
    cout<< u1<<endl;
    cout<< u2<<endl;
    uuid_t u3("{01234567-89ab-cdef-0123-456789abcdef}");//字符串构造
    cout<<u3<<endl;
    cout<< uuid_t(u3, "test name gen")<<endl; //通过名字构造

    与字符串的转换:
     uuid不能直接获得一个uuid的字符串表示,但因为uuid支持流输入输出,故可以使用std::stringstream转换为字符串,例如;
    uuid u = string_generator()("01234567-89ab-cdef-0123-456789abcdef");
    stringstream ss;
    ss << u; //uuid输出到字符串流
    string str;
    ss>>str;//字符串流输出到字符串对象
    cout<<str<<endl;

    另一个Boost库组件lexical_cast,它可以方便地实现字符串与uuid的双向转换
    示例:
    #include <iostream>
    #include <vector>
    #include <assert.h>
    #include <boost/uuid/uuid.hpp>
    #include <boost/uuid/uuid_generators.hpp>
    #include <boost/uuid/uuid_io.hpp>
    #include <boost/lexical_cast.hpp>
    using namespace boost;
    using namespace boost::uuids;
    using namespace std;
    int main()
    {
     uuid u = lexical_cast<uuid>("01234567-89ab-cdef-0123-456789abcdef");
     cout<<u<<endl;
     string str = lexical_cast<string>(u);  //uuid转换到字符串
     cout<<str<<endl;
    }
     lexical_cast的字符串转换uuid的用法很类似字符串生成器string_generator,但功能要弱很多,因为lexical_cast的转换功能是基于uuid的流输入能力,因此只能接受连字符格式的字符串,而且不能有花括号.

    SHA1摘要算法:
     SHA1算法广泛地应用于防篡改,身份鉴定等安全认证领域.
    #include <boost/uuid/sha1.hpp>
    boost::uuids::detail
    shal类的用法很简单,使用成员函数process_byte(),process_block()和process_bytes()以不用的方式把数据"喂"给shal对象,当输入所有数据后用get_digest()获得计算出的摘要值。
    示例:
    #include <iostream>
    #include <vector>
    #include <assert.h>
    #include <boost/uuid/uuid.hpp>
    #include <boost/uuid/uuid_generators.hpp>
    #include <boost/uuid/uuid_io.hpp>
    #include <boost/lexical_cast.hpp>
    #include <boost/uuid/sha1.hpp>
    using namespace boost;
    using namespace boost::uuids::detail;
    using namespace std;
    int main()
    {
     sha1 sha;

     char *szMsg = "a short message";   //用于摘要的消息
     sha.process_byte(0x10);      //处理一个字节
     sha.process_bytes(szMsg, strlen(szMsg)); //处理多个字节
     sha.process_block(szMsg, szMsg + strlen(szMsg));
     unsigned int digest[5];      //摘要的返回值
     sha.get_digest(digest);
     for (int i = 0; i< 5; ++i)
      cout<< hex << digest[i];    //16进制输出
    }

  • 相关阅读:
    Codeforces Round #229
    A Funny Game(博弈论)
    01背包模板
    一月24日新生冬季练习赛解题报告H.排列问题
    一月24日新生冬季练习赛解题报告F.棋盘
    POJ 2240Arbitrage
    POJ 3660Cow Contest
    POJ 3259Wormholes
    POJ 1860Currency Exchange
    HDU 4027Can you answer these queries?
  • 原文地址:https://www.cnblogs.com/lidabo/p/3897297.html
Copyright © 2011-2022 走看看