00001
00002
00003
00004
00005
00006
00007
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 {
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,
00043 PION_ID_HEX_BYTES = 16 * 2 + 4
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))
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
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
00161 static boost::uint64_t seed_seed_64 = (time(NULL) * 1000000) + boost::posix_time::microsec_clock::local_time().time_of_day().total_microseconds();
00162
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
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
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
00188
00189 data[8] &= 0xBF;
00190 data[8] |= 0x80;
00191
00192
00193
00194 data[6] &= 0x4F;
00195 data[6] |= 0x40;
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 }
00271
00272 #endif