pion-net
4.0.9
|
00001 // ----------------------------------------------------------------------- 00002 // pion-common: a collection of common libraries used by the Pion Platform 00003 // ----------------------------------------------------------------------- 00004 // Copyright (C) 2007-2009 Atomic Labs, Inc. (http://www.atomiclabs.com) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #ifndef __PION_PIONID_HEADER__ 00011 #define __PION_PIONID_HEADER__ 00012 00013 #include <string> 00014 #include <limits> 00015 #include <ctime> 00016 #include <cstring> 00017 #include <cstdlib> 00018 #include <boost/functional/hash.hpp> 00019 #include <boost/date_time/posix_time/posix_time.hpp> 00020 #include <boost/random/uniform_int.hpp> 00021 #include <boost/random/variate_generator.hpp> 00022 #include <boost/random/mersenne_twister.hpp> 00023 #include <boost/numeric/conversion/cast.hpp> 00024 #include <pion/PionConfig.hpp> 00025 00026 namespace pion { // begin namespace pion 00027 00028 00032 class PionId { 00033 public: 00034 00036 typedef unsigned char * iterator; 00037 00039 typedef const unsigned char * const_iterator; 00040 00041 enum { 00042 PION_ID_DATA_BYTES = 16, //< total number of data bytes 00043 PION_ID_HEX_BYTES = 16 * 2 + 4 //< number of bytes in hexadecimal representation 00044 }; 00045 00047 virtual ~PionId() {} 00048 00050 PionId(void) { 00051 typedef boost::mt19937 gen_type; 00052 typedef boost::uniform_int<unsigned long> dist_type; 00053 typedef boost::variate_generator<gen_type,dist_type> die_type; 00054 gen_type rng_gen(PionId::make_seed()); 00055 dist_type rng_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()); 00056 die_type rng_die(rng_gen, rng_dist); 00057 generate(m_data, rng_die); 00058 } 00059 00061 explicit PionId(const std::string& str) { 00062 from_string(str.c_str()); 00063 } 00064 00066 explicit PionId(const char *str) { 00067 from_string(str); 00068 } 00069 00071 template<typename base_generator_type, typename distribution_type> 00072 explicit PionId(boost::variate_generator<base_generator_type, distribution_type>& rng) { 00073 generate(m_data, rng); 00074 } 00075 00077 PionId(const PionId& id) { 00078 memcpy(m_data, id.m_data, PION_ID_DATA_BYTES); 00079 } 00080 00082 PionId& operator=(const PionId& id) { 00083 memcpy(m_data, id.m_data, PION_ID_DATA_BYTES); 00084 return *this; 00085 } 00086 00088 inline unsigned char operator[](const std::size_t n) const { 00089 return m_data[n]; 00090 } 00091 00093 inline bool operator==(const PionId& id) const { 00094 return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) == 0); 00095 } 00096 00098 inline bool operator!=(const PionId& id) const { 00099 return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) != 0); 00100 } 00101 00103 inline bool operator<(const PionId& id) const { 00104 return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) < 0); 00105 } 00106 00108 inline bool operator>(const PionId& id) const { 00109 return (memcmp(m_data, id.m_data, PION_ID_DATA_BYTES) > 0); 00110 } 00111 00113 inline iterator begin(void) { return m_data; } 00114 00116 inline iterator end(void) { return m_data + PION_ID_DATA_BYTES; } 00117 00119 inline const_iterator begin(void) const { return m_data; } 00120 00122 inline const_iterator end(void) const { return m_data + PION_ID_DATA_BYTES; } 00123 00125 inline std::string to_string(void) const { 00126 std::string hex_str; 00127 static const char hex[] = "0123456789abcdef"; 00128 for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i++) { 00129 hex_str += hex[m_data[i] >> 4]; 00130 hex_str += hex[m_data[i] & 0x0f]; 00131 if (i == 3 || i == 5 || i == 7 || i == 9) 00132 hex_str += '-'; 00133 } 00134 return hex_str; 00135 } 00136 00138 void from_string(const char *str) { 00139 std::size_t data_pos = 0; 00140 char buf[3]; 00141 buf[2] = '\0'; 00142 while (*str != '\0' && data_pos < PION_ID_DATA_BYTES) { 00143 if (isxdigit(*str)) { 00144 buf[0] = *str; 00145 if (*(++str) == '\0' || !isxdigit(*str)) // sanity check 00146 break; 00147 buf[1] = *str; 00148 m_data[data_pos++] = boost::numeric_cast<unsigned char>(strtoul(buf, NULL, 16)); 00149 } 00150 ++str; 00151 } 00152 } 00153 00155 static inline boost::uint32_t make_seed(void) { 00156 // this could probably be much better, but trying to KISS... 00157 typedef boost::mt19937 gen_type; 00158 typedef boost::uniform_int<unsigned long> dist_type; 00159 typedef boost::variate_generator<gen_type,dist_type> die_type; 00160 // initialize a static generator with seed based upon system time 00161 static boost::uint64_t seed_seed_64 = (time(NULL) * 1000000) + boost::posix_time::microsec_clock::local_time().time_of_day().total_microseconds(); 00162 // Convert to 32 bits, keeping most of the available entropy. 00163 static gen_type::result_type seed_seed_32 = boost::numeric_cast<gen_type::result_type>((seed_seed_64 >> 32) ^ (seed_seed_64 & 0xFFFFFFFF)); 00164 static gen_type rng_gen(seed_seed_32); 00165 static dist_type rng_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()); 00166 static die_type rng_die(rng_gen, rng_dist); 00167 // use the static rng to produce seed values that initialize other generators 00168 return rng_die(); 00169 } 00170 00171 00172 protected: 00173 00180 template<typename base_generator_type, typename distribution_type> 00181 static inline void generate(unsigned char *data, boost::variate_generator<base_generator_type, distribution_type>& rng) { 00182 // Note: this code is adapted from the Boost UUID library, (c) 2006 Andy Tompkins 00183 for (std::size_t i = 0; i < PION_ID_DATA_BYTES; i += sizeof(unsigned long)) { 00184 *reinterpret_cast<unsigned long*>(&data[i]) = rng(); 00185 } 00186 00187 // set variant 00188 // should be 0b10xxxxxx 00189 data[8] &= 0xBF; 00190 data[8] |= 0x80; 00191 00192 // set version 00193 // should be 0b0100xxxx 00194 data[6] &= 0x4F; //0b01001111 00195 data[6] |= 0x40; //0b01000000 00196 } 00197 00199 unsigned char m_data[PION_ID_DATA_BYTES]; 00200 }; 00201 00202 00204 static inline std::size_t hash_value(const PionId& id) { 00205 std::size_t seed = 0; 00206 const unsigned char * data = id.begin(); 00207 const unsigned char * const end = id.end(); 00208 while (data < end) { 00209 boost::hash_combine(seed, *reinterpret_cast<const unsigned long*>(data)); 00210 data += sizeof(unsigned long); 00211 } 00212 return seed; 00213 } 00214 00215 00219 template <typename BaseGeneratorType> 00220 class PionIdGeneratorBase { 00221 public: 00222 00224 typedef BaseGeneratorType base_generator_type; 00225 00227 typedef boost::uniform_int<unsigned long> distribution_type; 00228 00230 typedef boost::variate_generator<base_generator_type, distribution_type> gen_type; 00231 00232 00234 virtual ~PionIdGeneratorBase() {} 00235 00237 PionIdGeneratorBase(void) 00238 : m_random_gen(PionId::make_seed()), 00239 m_random_dist((std::numeric_limits<unsigned long>::min)(), (std::numeric_limits<unsigned long>::max)()), 00240 m_random_die(m_random_gen, m_random_dist) 00241 {} 00242 00244 inline PionId operator()(void) { return PionId(m_random_die); } 00245 00247 inline gen_type& getRNG(void) { return m_random_die; } 00248 00250 inline unsigned long getNumber(void) { return m_random_die(); } 00251 00252 00253 protected: 00254 00256 base_generator_type m_random_gen; 00257 00259 distribution_type m_random_dist; 00260 00262 gen_type m_random_die; 00263 }; 00264 00265 00267 typedef PionIdGeneratorBase<boost::mt19937> PionIdGenerator; 00268 00269 00270 } // end namespace pion 00271 00272 #endif