![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* id.h -*- C++ -*- 00002 Jeremy Barnes, 17 February 2012 00003 Copyright (c) 2012 Datacratic. All rights reserved. 00004 00005 Basic ID type for binary IDs of all types. 00006 */ 00007 00008 #pragma once 00009 00010 #include "city.h" // Google city hash function 00011 #include <string> 00012 #include "jml/utils/unnamed_bool.h" 00013 #include "jml/db/persistent_fwd.h" 00014 #include "jml/utils/less.h" 00015 #include "jml/arch/exception.h" 00016 00017 namespace Json { 00018 struct Value; 00019 } // namespace Json 00020 00021 namespace Datacratic { 00022 00023 /* 00024 JTzfCLBhlbWSsdZjcJ4wO4 00025 00026 Google ID: --> CAESEAYra3NIxLT9C8twKrzqaA 00027 AGID: --> 0828398c-5965-11e0-84c8-0026b937c8e1 00028 ANID: --> 7394206091425759590 00029 00030 00031 0828398c-5965-11e0-84c8-0026b937c8e1 00032 32 16 16 16 48 00033 00034 AYra3NIxLT9C8twKrzqaA 00035 00036 21 * 6 = 126 bits so 128 bits 00037 */ 00038 00039 /*****************************************************************************/ 00040 /* ID */ 00041 /*****************************************************************************/ 00042 00046 struct Id { 00047 00048 enum Type { 00049 NONE = 0, 00050 NULLID = 1, 00051 UUID = 2, 00052 GOOG128 = 3, 00053 BIGDEC = 4, 00054 BASE64_96 = 5, 00055 00056 // other integer-encoded values go here 00057 00058 STR = 192, 00059 //CUSTOM = 6 /// custom type with custom handlers 00060 00061 COMPOUND2 = 193, 00062 00063 // other string-encoded values go here 00064 00065 UNKNOWN = 255 00066 }; 00067 00068 Id() 00069 : type(NONE), val1(0), val2(0) 00070 { 00071 } 00072 00073 ~Id() 00074 { 00075 if (type >= STR) 00076 complexDestroy(); 00077 } 00078 00079 explicit Id(const std::string & value, 00080 Type type = UNKNOWN) 00081 : type(NONE), val1(0), val2(0) 00082 { 00083 parse(value, type); 00084 } 00085 00086 explicit Id(uint64_t value): 00087 type(BIGDEC), 00088 val1(value),val2(0) 00089 { 00090 } 00091 00092 00093 // Construct a compound ID from two others 00094 Id(const Id & underlying1, const Id & underlying2) 00095 : type(COMPOUND2), 00096 cmp1(new Id(underlying1)), 00097 cmp2(new Id(underlying2)) 00098 { 00099 } 00100 00101 Id(Id && other) 00102 : type(other.type), 00103 val1(other.val1), val2(other.val2) 00104 { 00105 other.type = NONE; 00106 } 00107 00108 Id(const Id & other) 00109 : type(other.type), 00110 val1(other.val1), val2(other.val2) 00111 { 00112 if (other.type >= STR) 00113 complexFinishCopy(); 00114 } 00115 00116 Id & operator = (Id && other) 00117 { 00118 if (type >= STR) 00119 complexDestroy(); 00120 type = other.type; 00121 val1 = other.val1; 00122 val2 = other.val2; 00123 other.type = NONE; 00124 return *this; 00125 } 00126 00127 Id & operator = (const Id & other) 00128 { 00129 if (type >= STR) 00130 complexDestroy(); 00131 type = other.type; 00132 val1 = other.val1; 00133 val2 = other.val2; 00134 if (other.type >= STR) 00135 complexFinishCopy(); 00136 return *this; 00137 } 00138 00139 void parse(const std::string & value, Type type = UNKNOWN); 00140 00141 std::string toString() const; 00142 00143 uint64_t toInt() const 00144 { 00145 if (type != BIGDEC) 00146 throw ML::Exception("can't convert non-BIGDEC to int"); 00147 return val1; 00148 } 00149 00150 //operator std::string () const 00151 //{ 00152 // return toString(); 00153 //} 00154 00155 bool notNull() const 00156 { 00157 return type >= NULLID 00158 && val != 0; 00159 } 00160 00161 JML_IMPLEMENT_OPERATOR_BOOL(notNull()); 00162 00163 bool operator == (const Id & other) const 00164 { 00165 if (type != other.type) return false; 00166 if (type == NONE || type == NULLID) return true; 00167 if (JML_UNLIKELY(type >= STR)) return complexEqual(other); 00168 return val == other.val; 00169 } 00170 00171 bool operator != (const Id & other) const 00172 { 00173 return ! operator == (other); 00174 } 00175 00176 bool operator < (const Id & other) const 00177 { 00178 if (type < other.type) return true; 00179 if (other.type < type) return false; 00180 if (JML_UNLIKELY(type >= STR)) return complexLess(other); 00181 return val < other.val; 00182 } 00183 00184 uint64_t hash() const 00185 { 00186 if (type == NONE || type == NULLID) return 0; 00187 if (JML_UNLIKELY(type >= STR)) return complexHash(); 00188 return Hash128to64(std::make_pair(val1, val2)); 00189 } 00190 00191 bool complexEqual(const Id & other) const; 00192 bool complexLess(const Id & other) const; 00193 uint64_t complexHash() const; 00194 void complexDestroy(); 00195 void complexFinishCopy(); 00196 00197 uint8_t type; 00198 uint8_t unused[3]; 00199 00200 union { 00201 // 128 byte integer 00202 struct { 00203 uint64_t val1; 00204 uint64_t val2; 00205 }; 00206 00207 struct { 00208 uint32_t v1h, v1l; 00209 uint32_t v2h, v2l; 00210 }; 00211 00212 __uint128_t val; 00213 00214 // uuid 00215 struct { 00216 uint64_t f1:32; 00217 uint64_t f2:16; 00218 uint64_t f3:16; 00219 uint64_t f4:16; 00220 uint64_t f5:48; 00221 }; 00222 00223 // string 00224 struct { 00225 uint64_t len:56; 00226 uint64_t ownstr:8; 00227 const char * str; 00228 }; 00229 00230 // compound2 00231 struct { 00232 Id * cmp1; 00233 Id * cmp2; 00234 }; 00235 #if 0 00236 // custom 00237 struct { 00238 void * data; 00239 uint64_t (*controlFn) (int, Id *, Id *); 00240 }; 00241 #endif 00242 }; 00243 00245 const Id & compoundId1() const; 00246 00248 const Id & compoundId2() const; 00249 00250 void serialize(ML::DB::Store_Writer & store) const; 00251 void reconstitute(ML::DB::Store_Reader & store); 00252 00253 Json::Value toJson() const; 00254 static Id fromJson(const Json::Value & val); 00255 } JML_PACKED; 00256 00257 IMPL_SERIALIZE_RECONSTITUTE(Id); 00258 00259 inline std::ostream & operator << (std::ostream & stream, const Id & id) 00260 { 00261 return stream << id.toString(); 00262 } 00263 00264 inline std::istream & operator >> (std::istream & stream, Id & id) 00265 { 00266 std::string s; 00267 stream >> s; 00268 id.parse(s); 00269 return stream; 00270 } 00271 00272 } // namespace Datacratic 00273 00274 namespace std { 00275 00276 template<typename T> struct hash; 00277 00278 template<> 00279 struct hash<Datacratic::Id> : public std::unary_function<Datacratic::Id, size_t> 00280 { 00281 size_t operator()(const Datacratic::Id & id) const { return id.hash(); } 00282 }; 00283 00284 } // namespace std