[UUID] Code for UUIDs as PODs and other changes

I remarked the other day that a UUID has a well-defined, portable binary format, so I took a bit of time to rearrange things to make the UUID class a POD and make more use of the generators idea. Along the way I made a few other changes. I've uploaded the result (with updated docs) to the vault as uuid_alt_v13_pod.zip : http://www.boostpro.com/vault/index.php?action=downloadfile&filename=uuid_alt_v13_pod.zip Some elaboration follows below. Comments appreciated. ~ Scott PODness: As a POD, all the constructors are of course gone. This doesn't bother me, but I have no idea what others will think. In fact, I like it better, since I don't think that serialization to and from strings belongs in the type, and it seems like using a lexical_cast is perfectly reasonable: uuid u = lexical_cast<uuid>("21f7f8de-8051-5b89-8680-0195ef798b6a"); This cuts out a large chunk of code, too. I don't know if it's useful, but aggregate syntax also opens possibilities: uuid u = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }; In a possibly controversial move, I changed everything that could throw exceptions. That's not that much, though. The std::string parsing code I had already removed, which was the only source of one exception. The other came from the byte input iterator range constructor, which I kept as an assign member function (though I made mutable iterators available, so it's unnecessary). In there I switched the throw to an assert, assuming that it's reasonable for people to arrange for there to always be 16 elements as a precondition, since it's raw construction (which is used into the generators, for example) rather than something likely to come from user input. Include cost: I took the opportunity to move the stream I/O code out to its own header, like the serialization code is. This means that the uuids/uuid.hpp header is fairly light, as the <locale> and <string> includes are gone. In fact, all that's left are these: #include <boost/array.hpp> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/cstdint.hpp> #include <boost/numeric/conversion/cast.hpp> #include <boost/static_assert.hpp> Generators: I liked the idea of using a generator object for the random UUIDs, so I wanted to extend that idea. I renamed it to random_generator, on the theory that random_generator<> isn't strenuous if a user wants the default PRNG. boost::uuids::random_generator<> gen1; boost::uuids::uuid u1 = gen1(); boost::lagged_fibonacci44497 rng; boost::uuids::random_generator<boost::lagged_fibonacci44497&> gen2(rng); boost::uuids::uuid u2 = gen2(); For name-based, I introduced a sha1_generator class. This is seeded with a namespace UUID (those from the RFC are provided in boost::uuids::namespaces), and then has an operator() that takes a byte input iterator range. It may be interesting to add a boost.range overload, allowing the generator to be used as a transform functor for strings. boost::uuids::sha1_generator gen(boost::uuids::namespaces::dns()); std::string name = "www.widgets.com"; boost::uuid u = gen(name.begin(), name.end()); Native UUIDs: I recall that someone in the review wanted an interface to the OS functionality, and I had been looking at Linux's earlier, so I wrote up 2 additional generators. e2fsprogs_generator uses the <uuid/uuid.h> header and libuuid on Linux, and passes all the tests that random_generator does. windows_generator uses UuidCreate, and is completely untested. Variants and Versions: I thought being able to find out these might be a good idea, so they're there too. enum variant_type {variant_ncs = 0, variant_dce = 1, variant_rfc_4122 = variant_dce, variant_microsoft = 2, variant_other = 3}; variant_type variant() const; enum version_type {version_wrong_variant = -1, version_unknown = 0, version_1 = 1, version_time_based = version_1, version_2 = 2, version_dce_security = version_2, version_3 = 3, version_name_based_md5 = version_3, version_4 = 4, version_random = version_4, version_5 = 5, version_name_based_sha1 = version_5}; version_type version() const; Implementation Details: I switched sha1.hpp over to using int32_t to remove the 4-byte-int requirement. I also let it handle 512 MiB+ messages (if size_t can), though that's not a serious concern. I replaced the *reinterpret_cast<unsigned long*> in random_generator with the kind of code used in sha1 that doesn't have the endianness dependence or what I think is an aliasing violation.
participants (1)
-
Scott McMurray