| 1 | // [License]
 | 
|---|
| 2 | // The Ariba-Underlay Copyright
 | 
|---|
| 3 | //
 | 
|---|
| 4 | // Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
 | 
|---|
| 5 | //
 | 
|---|
| 6 | // Institute of Telematics
 | 
|---|
| 7 | // UniversitÀt Karlsruhe (TH)
 | 
|---|
| 8 | // Zirkel 2, 76128 Karlsruhe
 | 
|---|
| 9 | // Germany
 | 
|---|
| 10 | //
 | 
|---|
| 11 | // Redistribution and use in source and binary forms, with or without
 | 
|---|
| 12 | // modification, are permitted provided that the following conditions are
 | 
|---|
| 13 | // met:
 | 
|---|
| 14 | //
 | 
|---|
| 15 | // 1. Redistributions of source code must retain the above copyright
 | 
|---|
| 16 | // notice, this list of conditions and the following disclaimer.
 | 
|---|
| 17 | // 2. Redistributions in binary form must reproduce the above copyright
 | 
|---|
| 18 | // notice, this list of conditions and the following disclaimer in the
 | 
|---|
| 19 | // documentation and/or other materials provided with the distribution.
 | 
|---|
| 20 | //
 | 
|---|
| 21 | // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
 | 
|---|
| 22 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
|---|
| 23 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
|---|
| 24 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
 | 
|---|
| 25 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
|---|
| 26 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
|---|
| 27 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
|---|
| 28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
|---|
| 29 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
|---|
| 30 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
|---|
| 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
|---|
| 32 | //
 | 
|---|
| 33 | // The views and conclusions contained in the software and documentation
 | 
|---|
| 34 | // are those of the authors and should not be interpreted as representing
 | 
|---|
| 35 | // official policies, either expressed or implied, of the Institute of
 | 
|---|
| 36 | // Telematics.
 | 
|---|
| 37 | // [License]
 | 
|---|
| 38 | 
 | 
|---|
| 39 | #include "Identifier.h"
 | 
|---|
| 40 | #include "ariba/utility/misc/sha1.h"
 | 
|---|
| 41 | 
 | 
|---|
| 42 | namespace ariba {
 | 
|---|
| 43 | namespace utility {
 | 
|---|
| 44 | 
 | 
|---|
| 45 | uint Identifier::keyLength = MAX_KEYLENGTH;
 | 
|---|
| 46 | 
 | 
|---|
| 47 | uint Identifier::aSize = Identifier::keyLength / (8 * sizeof(mp_limb_t))
 | 
|---|
| 48 |                 + (Identifier::keyLength % (8 * sizeof(mp_limb_t)) != 0 ? 1 : 0);
 | 
|---|
| 49 | 
 | 
|---|
| 50 | mp_limb_t Identifier::GMP_MSB_MASK = (Identifier::keyLength % GMP_LIMB_BITS)
 | 
|---|
| 51 |                 != 0 ? (((mp_limb_t) 1 << (Identifier::keyLength % GMP_LIMB_BITS)) - 1)
 | 
|---|
| 52 |                 : (mp_limb_t) -1;
 | 
|---|
| 53 | 
 | 
|---|
| 54 | /* virtual serialization */
 | 
|---|
| 55 | vsznDefault(Identifier);
 | 
|---|
| 56 | use_logging_cpp( Identifier );
 | 
|---|
| 57 | 
 | 
|---|
| 58 | //--------------------------------------------------------------------
 | 
|---|
| 59 | // constants
 | 
|---|
| 60 | //--------------------------------------------------------------------
 | 
|---|
| 61 | 
 | 
|---|
| 62 | // predefined keys
 | 
|---|
| 63 | const Identifier Identifier::UNSPECIFIED_KEY;
 | 
|---|
| 64 | const Identifier Identifier::ZERO((uint32_t) 0);
 | 
|---|
| 65 | const Identifier Identifier::ONE((uint32_t) 1);
 | 
|---|
| 66 | 
 | 
|---|
| 67 | // hex crap
 | 
|---|
| 68 | const char* HEX = "0123456789abcdef";
 | 
|---|
| 69 | gmp_randstate_t randstate;
 | 
|---|
| 70 | 
 | 
|---|
| 71 | void Identifier::clearAddress() {
 | 
|---|
| 72 |         for (int i = 0; i < array_size; i++)
 | 
|---|
| 73 |                 key[i] = 0;
 | 
|---|
| 74 |         isUnspec = false;
 | 
|---|
| 75 |         trim();
 | 
|---|
| 76 | }
 | 
|---|
| 77 | 
 | 
|---|
| 78 | bool Identifier::setAddress(string address) {
 | 
|---|
| 79 |         // TODO
 | 
|---|
| 80 | }
 | 
|---|
| 81 | 
 | 
|---|
| 82 | string Identifier::getAddress() const {
 | 
|---|
| 83 |         return toString();
 | 
|---|
| 84 | }
 | 
|---|
| 85 | 
 | 
|---|
| 86 | //--------------------------------------------------------------------
 | 
|---|
| 87 | // construction and destruction
 | 
|---|
| 88 | //--------------------------------------------------------------------
 | 
|---|
| 89 | 
 | 
|---|
| 90 | // default construction: create a unspecified node key
 | 
|---|
| 91 | Identifier::Identifier() {
 | 
|---|
| 92 |         seed();
 | 
|---|
| 93 |         isUnspec = true;
 | 
|---|
| 94 |         trim();
 | 
|---|
| 95 | }
 | 
|---|
| 96 | 
 | 
|---|
| 97 | // create a key out of an normal integer
 | 
|---|
| 98 | Identifier::Identifier(uint32_t num) {
 | 
|---|
| 99 |         seed();
 | 
|---|
| 100 |         clearAddress();
 | 
|---|
| 101 |         key[0] = (uint32_t) num;
 | 
|---|
| 102 |         trim();
 | 
|---|
| 103 | }
 | 
|---|
| 104 | 
 | 
|---|
| 105 | // create a key out of a buffer
 | 
|---|
| 106 | Identifier::Identifier(const unsigned char* buf, uint size) {
 | 
|---|
| 107 |         seed();
 | 
|---|
| 108 |         int trimSize, offset;
 | 
|---|
| 109 |         clearAddress();
 | 
|---|
| 110 |         trimSize = (int) std::min((uint) (aSize * sizeof(mp_limb_t)), size);
 | 
|---|
| 111 |         offset = aSize * sizeof(mp_limb_t) - trimSize;
 | 
|---|
| 112 |         memcpy(((char*) key) + offset, buf, trimSize);
 | 
|---|
| 113 |         trim();
 | 
|---|
| 114 | }
 | 
|---|
| 115 | 
 | 
|---|
| 116 | // create a key out of an string with the given base
 | 
|---|
| 117 | Identifier::Identifier(const std::string& str, uint base) {
 | 
|---|
| 118 |         seed();
 | 
|---|
| 119 | 
 | 
|---|
| 120 |         if ((base < 2) || (base > 16)) {
 | 
|---|
| 121 |                 logging_error( "Identifier::Identifier(): Invalid base!" );
 | 
|---|
| 122 |                 return;
 | 
|---|
| 123 |         }
 | 
|---|
| 124 | 
 | 
|---|
| 125 |         string s(str);
 | 
|---|
| 126 |         clearAddress();
 | 
|---|
| 127 | 
 | 
|---|
| 128 |         for (uint i = 0; i < s.size(); i++) {
 | 
|---|
| 129 |                 if ((s[i] >= '0') && (s[i] <= '9')) {
 | 
|---|
| 130 |                         s[i] -= '0';
 | 
|---|
| 131 |                 } else if ((s[i] >= 'a') && (s[i] <= 'f')) {
 | 
|---|
| 132 |                         s[i] -= ('a' - 10);
 | 
|---|
| 133 |                 } else if ((s[i] >= 'A') & (s[i] <= 'F')) {
 | 
|---|
| 134 |                         s[i] -= ('A' - 10);
 | 
|---|
| 135 |                 } else {
 | 
|---|
| 136 |                         logging_error( "Identifier::Identifier(): "
 | 
|---|
| 137 |                                         "Invalid character in string!" );
 | 
|---|
| 138 |                         return;
 | 
|---|
| 139 |                 }
 | 
|---|
| 140 |         }
 | 
|---|
| 141 | 
 | 
|---|
| 142 |         mpn_set_str((mp_limb_t*) this->key, (const unsigned char*) s.c_str(),
 | 
|---|
| 143 |                         str.size(), base);
 | 
|---|
| 144 |         trim();
 | 
|---|
| 145 | }
 | 
|---|
| 146 | 
 | 
|---|
| 147 | // copy constructor
 | 
|---|
| 148 | Identifier::Identifier(const Identifier& rhs) {
 | 
|---|
| 149 |         seed();
 | 
|---|
| 150 |         (*this) = rhs;
 | 
|---|
| 151 | }
 | 
|---|
| 152 | 
 | 
|---|
| 153 | // default destructur
 | 
|---|
| 154 | Identifier::~Identifier() {
 | 
|---|
| 155 | }
 | 
|---|
| 156 | 
 | 
|---|
| 157 | void Identifier::seed(){
 | 
|---|
| 158 |         static bool isSeeded = false;
 | 
|---|
| 159 |         if( isSeeded ) return;
 | 
|---|
| 160 | 
 | 
|---|
| 161 |         gmp_randinit_default( randstate );
 | 
|---|
| 162 |         gmp_randseed_ui( randstate, time(NULL) );
 | 
|---|
| 163 | 
 | 
|---|
| 164 |         isSeeded = true;
 | 
|---|
| 165 | }
 | 
|---|
| 166 | 
 | 
|---|
| 167 | //--------------------------------------------------------------------
 | 
|---|
| 168 | // string representations & node key attributes
 | 
|---|
| 169 | //--------------------------------------------------------------------
 | 
|---|
| 170 | 
 | 
|---|
| 171 | void Identifier::setKeyLength(uint length) {
 | 
|---|
| 172 |         if ((length < 1) || (length > Identifier::keyLength)) {
 | 
|---|
| 173 | 
 | 
|---|
| 174 |                 logging_error( "Identifier::setKeyLength(): length must be <= " <<
 | 
|---|
| 175 |                                 MAX_KEYLENGTH << " and setKeyLength() must not be " <<
 | 
|---|
| 176 |                                 "called twice with different length!" );
 | 
|---|
| 177 |                 return;
 | 
|---|
| 178 |         }
 | 
|---|
| 179 | 
 | 
|---|
| 180 |         keyLength = length;
 | 
|---|
| 181 | 
 | 
|---|
| 182 |         aSize = keyLength / (8 * sizeof(mp_limb_t)) + (keyLength % (8
 | 
|---|
| 183 |                         * sizeof(mp_limb_t)) != 0 ? 1 : 0);
 | 
|---|
| 184 | 
 | 
|---|
| 185 |         GMP_MSB_MASK = (keyLength % GMP_LIMB_BITS) != 0 ? (((mp_limb_t) 1
 | 
|---|
| 186 |                         << (keyLength % GMP_LIMB_BITS)) - 1) : (mp_limb_t) -1;
 | 
|---|
| 187 | }
 | 
|---|
| 188 | 
 | 
|---|
| 189 | // returns the length in bits
 | 
|---|
| 190 | uint Identifier::getLength() {
 | 
|---|
| 191 |         return Identifier::keyLength;
 | 
|---|
| 192 | }
 | 
|---|
| 193 | 
 | 
|---|
| 194 | bool Identifier::isUnspecified() const {
 | 
|---|
| 195 |         return isUnspec;
 | 
|---|
| 196 | }
 | 
|---|
| 197 | 
 | 
|---|
| 198 | std::string Identifier::toString(uint base) const {
 | 
|---|
| 199 |         if ((base < 2) || (base > 16)) {
 | 
|---|
| 200 |                 logging_error( "Identifier::Identifier(): Invalid base!" );
 | 
|---|
| 201 |                 return "";
 | 
|---|
| 202 |         }
 | 
|---|
| 203 | 
 | 
|---|
| 204 |         if (isUnspec) return std::string("<unspec>");
 | 
|---|
| 205 | 
 | 
|---|
| 206 |         char temp[80];
 | 
|---|
| 207 |         if (base == 16) {
 | 
|---|
| 208 |                 int k = 0;
 | 
|---|
| 209 |                 for (int i = (keyLength - 1) / 4; i >= 0; i--, k++) {
 | 
|---|
| 210 |                         temp[k] = HEX[this->get(4 * i, 4)];
 | 
|---|
| 211 |                 }
 | 
|---|
| 212 |                 temp[k] = 0;
 | 
|---|
| 213 |                 return std::string((const char*) temp);
 | 
|---|
| 214 |         } else if (base == 2) {
 | 
|---|
| 215 |                 int k = 0;
 | 
|---|
| 216 |                 for (int i = MAX_KEYLENGTH - 1; i >= 0; i -= 1, k++)
 | 
|---|
| 217 |                         temp[k] = HEX[this->get(i, 1)];
 | 
|---|
| 218 |                 temp[k] = 0;
 | 
|---|
| 219 |                 return std::string((const char*) temp);
 | 
|---|
| 220 |         }
 | 
|---|
| 221 |         //#endif
 | 
|---|
| 222 | #if 0
 | 
|---|
| 223 |         size_t log2[33] = {0};
 | 
|---|
| 224 |         log2[2] = 1;
 | 
|---|
| 225 |         log2[4] = 2;
 | 
|---|
| 226 |         log2[8] = 3;
 | 
|---|
| 227 |         log2[16] = 4;
 | 
|---|
| 228 |         log2[32] = 5;
 | 
|---|
| 229 |         size_t sh = (sizeof(mp_limb_t)*8/log2[base]);
 | 
|---|
| 230 |         //              key[array_size] = ~0;
 | 
|---|
| 231 |         mp_size_t last = mpn_get_str((unsigned char*) temp, base,
 | 
|---|
| 232 |                         (mp_limb_t*) this->key, aSize+1);
 | 
|---|
| 233 |         for (int i = 0; i < last-sh; i++) {
 | 
|---|
| 234 |                 temp[i] = HEX[temp[i+sh]];
 | 
|---|
| 235 |         }
 | 
|---|
| 236 |         temp[last-sh] = 0;
 | 
|---|
| 237 |         return std::string((const char*) temp);
 | 
|---|
| 238 | }
 | 
|---|
| 239 | #endif
 | 
|---|
| 240 | }
 | 
|---|
| 241 | 
 | 
|---|
| 242 | //--------------------------------------------------------------------
 | 
|---|
| 243 | // operators
 | 
|---|
| 244 | //--------------------------------------------------------------------
 | 
|---|
| 245 | 
 | 
|---|
| 246 | // assignment operator
 | 
|---|
| 247 | Identifier& Identifier::operator=(const Identifier& rhs) {
 | 
|---|
| 248 |         isUnspec = rhs.isUnspec;
 | 
|---|
| 249 |         memcpy(key, rhs.key, aSize * sizeof(mp_limb_t));
 | 
|---|
| 250 |         return *this;
 | 
|---|
| 251 | }
 | 
|---|
| 252 | 
 | 
|---|
| 253 | // sub one prefix operator
 | 
|---|
| 254 | Identifier& Identifier::operator--() {
 | 
|---|
| 255 |         return (*this -= ONE);
 | 
|---|
| 256 | }
 | 
|---|
| 257 | 
 | 
|---|
| 258 | // sub one postfix operator
 | 
|---|
| 259 | Identifier Identifier::operator--(int) {
 | 
|---|
| 260 |         Identifier clone = *this;
 | 
|---|
| 261 |         *this -= ONE;
 | 
|---|
| 262 |         return clone;
 | 
|---|
| 263 | }
 | 
|---|
| 264 | 
 | 
|---|
| 265 | // add one prefix operator
 | 
|---|
| 266 | Identifier& Identifier::operator++() {
 | 
|---|
| 267 |         return (*this += ONE);
 | 
|---|
| 268 | }
 | 
|---|
| 269 | 
 | 
|---|
| 270 | // sub one postfix operator
 | 
|---|
| 271 | Identifier Identifier::operator++(int) {
 | 
|---|
| 272 |         Identifier clone = *this;
 | 
|---|
| 273 |         *this += ONE;
 | 
|---|
| 274 |         return clone;
 | 
|---|
| 275 | }
 | 
|---|
| 276 | 
 | 
|---|
| 277 | // add assign operator
 | 
|---|
| 278 | Identifier& Identifier::operator+=(const Identifier& rhs) {
 | 
|---|
| 279 |         mpn_add_n((mp_limb_t*) key, (mp_limb_t*) key, (mp_limb_t*) rhs.key, aSize);
 | 
|---|
| 280 |         trim();
 | 
|---|
| 281 |         isUnspec = false;
 | 
|---|
| 282 |         return *this;
 | 
|---|
| 283 | }
 | 
|---|
| 284 | 
 | 
|---|
| 285 | // sub assign operator
 | 
|---|
| 286 | Identifier& Identifier::operator-=(const Identifier& rhs) {
 | 
|---|
| 287 |         mpn_sub_n((mp_limb_t*) key, (mp_limb_t*) key, (mp_limb_t*) rhs.key, aSize);
 | 
|---|
| 288 |         trim();
 | 
|---|
| 289 |         isUnspec = false;
 | 
|---|
| 290 |         return *this;
 | 
|---|
| 291 | }
 | 
|---|
| 292 | 
 | 
|---|
| 293 | // add operator
 | 
|---|
| 294 | Identifier Identifier::operator+(const Identifier& rhs) const {
 | 
|---|
| 295 |         Identifier result = *this;
 | 
|---|
| 296 |         result += rhs;
 | 
|---|
| 297 |         return result;
 | 
|---|
| 298 | }
 | 
|---|
| 299 | 
 | 
|---|
| 300 | // sub operator
 | 
|---|
| 301 | Identifier Identifier::operator-(const Identifier& rhs) const {
 | 
|---|
| 302 |         Identifier result = *this;
 | 
|---|
| 303 |         result -= rhs;
 | 
|---|
| 304 |         return result;
 | 
|---|
| 305 | }
 | 
|---|
| 306 | 
 | 
|---|
| 307 | // compare operators
 | 
|---|
| 308 | bool Identifier::operator<(const Identifier& compKey) const {
 | 
|---|
| 309 |         return compareTo(compKey) < 0;
 | 
|---|
| 310 | }
 | 
|---|
| 311 | bool Identifier::operator>(const Identifier& compKey) const {
 | 
|---|
| 312 |         return compareTo(compKey) > 0;
 | 
|---|
| 313 | }
 | 
|---|
| 314 | bool Identifier::operator<=(const Identifier& compKey) const {
 | 
|---|
| 315 |         return compareTo(compKey) <= 0;
 | 
|---|
| 316 | }
 | 
|---|
| 317 | bool Identifier::operator>=(const Identifier& compKey) const {
 | 
|---|
| 318 |         return compareTo(compKey) >= 0;
 | 
|---|
| 319 | }
 | 
|---|
| 320 | bool Identifier::operator==(const Identifier& compKey) const {
 | 
|---|
| 321 | 
 | 
|---|
| 322 |         if( this->isUnspecified() && compKey.isUnspecified() )
 | 
|---|
| 323 |                 return true;
 | 
|---|
| 324 |         else
 | 
|---|
| 325 |                 return compareTo(compKey) == 0;
 | 
|---|
| 326 | }
 | 
|---|
| 327 | bool Identifier::operator!=(const Identifier& compKey) const {
 | 
|---|
| 328 |         return compareTo(compKey) != 0;
 | 
|---|
| 329 | }
 | 
|---|
| 330 | 
 | 
|---|
| 331 | // bitwise xor
 | 
|---|
| 332 | Identifier Identifier::operator^(const Identifier& rhs) const {
 | 
|---|
| 333 |         Identifier result = *this;
 | 
|---|
| 334 |         for (uint i = 0; i < aSize; i++) {
 | 
|---|
| 335 |                 result.key[i] ^= rhs.key[i];
 | 
|---|
| 336 |         }
 | 
|---|
| 337 | 
 | 
|---|
| 338 |         return result;
 | 
|---|
| 339 | }
 | 
|---|
| 340 | 
 | 
|---|
| 341 | // bitwise or
 | 
|---|
| 342 | Identifier Identifier::operator|(const Identifier& rhs) const {
 | 
|---|
| 343 |         Identifier result = *this;
 | 
|---|
| 344 |         for (uint i = 0; i < aSize; i++) {
 | 
|---|
| 345 |                 result.key[i] |= rhs.key[i];
 | 
|---|
| 346 |         }
 | 
|---|
| 347 | 
 | 
|---|
| 348 |         return result;
 | 
|---|
| 349 | }
 | 
|---|
| 350 | 
 | 
|---|
| 351 | // bitwise and
 | 
|---|
| 352 | Identifier Identifier::operator&(const Identifier& rhs) const {
 | 
|---|
| 353 |         Identifier result = *this;
 | 
|---|
| 354 |         for (uint i = 0; i < aSize; i++) {
 | 
|---|
| 355 |                 result.key[i] &= rhs.key[i];
 | 
|---|
| 356 |         }
 | 
|---|
| 357 | 
 | 
|---|
| 358 |         return result;
 | 
|---|
| 359 | }
 | 
|---|
| 360 | 
 | 
|---|
| 361 | // complement
 | 
|---|
| 362 | Identifier Identifier::operator~() const {
 | 
|---|
| 363 |         Identifier result = *this;
 | 
|---|
| 364 |         for (uint i = 0; i < aSize; i++) {
 | 
|---|
| 365 |                 result.key[i] = ~key[i];
 | 
|---|
| 366 |         }
 | 
|---|
| 367 |         result.trim();
 | 
|---|
| 368 | 
 | 
|---|
| 369 |         return result;
 | 
|---|
| 370 | }
 | 
|---|
| 371 | 
 | 
|---|
| 372 | // bitwise shift right
 | 
|---|
| 373 | Identifier Identifier::operator>>(uint num) const {
 | 
|---|
| 374 |         Identifier result = ZERO;
 | 
|---|
| 375 |         int i = num / GMP_LIMB_BITS;
 | 
|---|
| 376 | 
 | 
|---|
| 377 |         num %= GMP_LIMB_BITS;
 | 
|---|
| 378 | 
 | 
|---|
| 379 |         if (i >= (int) aSize) return result;
 | 
|---|
| 380 | 
 | 
|---|
| 381 |         for (int j = 0; j < (int) aSize - i; j++) {
 | 
|---|
| 382 |                 result.key[j] = key[j + i];
 | 
|---|
| 383 |         }
 | 
|---|
| 384 |         mpn_rshift(result.key, result.key, aSize, num);
 | 
|---|
| 385 |         result.isUnspec = false;
 | 
|---|
| 386 |         result.trim();
 | 
|---|
| 387 | 
 | 
|---|
| 388 |         return result;
 | 
|---|
| 389 | }
 | 
|---|
| 390 | 
 | 
|---|
| 391 | // bitwise shift left
 | 
|---|
| 392 | Identifier Identifier::operator<<(uint num) const {
 | 
|---|
| 393 |         Identifier result = ZERO;
 | 
|---|
| 394 |         int i = num / GMP_LIMB_BITS;
 | 
|---|
| 395 | 
 | 
|---|
| 396 |         num %= GMP_LIMB_BITS;
 | 
|---|
| 397 | 
 | 
|---|
| 398 |         if (i >= (int) aSize) return result;
 | 
|---|
| 399 | 
 | 
|---|
| 400 |         for (int j = 0; j < (int) aSize - i; j++) {
 | 
|---|
| 401 |                 result.key[j + i] = key[j];
 | 
|---|
| 402 |         }
 | 
|---|
| 403 |         mpn_lshift(result.key, result.key, aSize, num);
 | 
|---|
| 404 |         result.isUnspec = false;
 | 
|---|
| 405 |         result.trim();
 | 
|---|
| 406 | 
 | 
|---|
| 407 |         return result;
 | 
|---|
| 408 | }
 | 
|---|
| 409 | 
 | 
|---|
| 410 | // get bit
 | 
|---|
| 411 | IdentifierBit Identifier::operator[](uint n) {
 | 
|---|
| 412 |         return IdentifierBit(get(n, 1), n, this);
 | 
|---|
| 413 | }
 | 
|---|
| 414 | 
 | 
|---|
| 415 | Identifier& Identifier::setBitAt(uint pos, bool value) {
 | 
|---|
| 416 |         mp_limb_t digit = 1;
 | 
|---|
| 417 |         digit = digit << (pos % GMP_LIMB_BITS);
 | 
|---|
| 418 | 
 | 
|---|
| 419 |         if (value) {
 | 
|---|
| 420 |                 key[pos / GMP_LIMB_BITS] |= digit;
 | 
|---|
| 421 |         } else {
 | 
|---|
| 422 |                 //key[pos / GMP_LIMB_BITS] = key[pos / GMP_LIMB_BITS] & ~digit;
 | 
|---|
| 423 |                 key[pos / GMP_LIMB_BITS] &= ~digit;
 | 
|---|
| 424 |         }
 | 
|---|
| 425 | 
 | 
|---|
| 426 |         return *this;
 | 
|---|
| 427 | }
 | 
|---|
| 428 | ;
 | 
|---|
| 429 | 
 | 
|---|
| 430 | //--------------------------------------------------------------------
 | 
|---|
| 431 | // additional math
 | 
|---|
| 432 | //--------------------------------------------------------------------
 | 
|---|
| 433 | 
 | 
|---|
| 434 | // returns a sub integer
 | 
|---|
| 435 | uint32_t Identifier::get(uint p, uint n) const {
 | 
|---|
| 436 |         int i = p / GMP_LIMB_BITS, // index of starting bit
 | 
|---|
| 437 |                         f = p % GMP_LIMB_BITS, // position of starting bit
 | 
|---|
| 438 |                         f2 = f + n - GMP_LIMB_BITS; // how many bits to take from next index
 | 
|---|
| 439 | 
 | 
|---|
| 440 |         if (p + n > Identifier::keyLength) {
 | 
|---|
| 441 |                 logging_error( "Identifier::get: Invalid range (index too large!)" );
 | 
|---|
| 442 |                 return 0;
 | 
|---|
| 443 |         }
 | 
|---|
| 444 | 
 | 
|---|
| 445 |         return ((key[i] >> f) | // get the bits of key[i]
 | 
|---|
| 446 |                         (f2 > 0 ? (key[i + 1] << (GMP_LIMB_BITS - f)) : 0)) & // the extra bits from key[i+1]
 | 
|---|
| 447 |                         (((uint32_t) (~0)) >> (GMP_LIMB_BITS - n)); // delete unused bits
 | 
|---|
| 448 | }
 | 
|---|
| 449 | 
 | 
|---|
| 450 | // fill suffix with random bits
 | 
|---|
| 451 | Identifier Identifier::randomSuffix(uint pos) const {
 | 
|---|
| 452 |         Identifier newKey = *this;
 | 
|---|
| 453 |         int i = pos / GMP_LIMB_BITS, j = pos % GMP_LIMB_BITS;
 | 
|---|
| 454 |         mp_limb_t m = ((mp_limb_t) 1 << j) - 1;
 | 
|---|
| 455 |         mp_limb_t rnd;
 | 
|---|
| 456 | 
 | 
|---|
| 457 |         mpn_random(&rnd, 1);
 | 
|---|
| 458 |         newKey.key[i] &= ~m;
 | 
|---|
| 459 |         newKey.key[i] |= (rnd & m);
 | 
|---|
| 460 |         mpn_random(newKey.key, i);
 | 
|---|
| 461 |         newKey.trim();
 | 
|---|
| 462 | 
 | 
|---|
| 463 |         return newKey;
 | 
|---|
| 464 | }
 | 
|---|
| 465 | 
 | 
|---|
| 466 | // fill prefix with random bits
 | 
|---|
| 467 | Identifier Identifier::randomPrefix(uint pos) const {
 | 
|---|
| 468 |         Identifier newKey = *this;
 | 
|---|
| 469 |         int i = pos / GMP_LIMB_BITS, j = pos % GMP_LIMB_BITS;
 | 
|---|
| 470 |         mp_limb_t m = ((mp_limb_t) 1 << j) - 1;
 | 
|---|
| 471 |         mp_limb_t rnd;
 | 
|---|
| 472 | 
 | 
|---|
| 473 |         mpn_random(&rnd, 1);
 | 
|---|
| 474 | 
 | 
|---|
| 475 |         newKey.key[i] &= m;
 | 
|---|
| 476 |         newKey.key[i] |= (rnd & ~m);
 | 
|---|
| 477 |         for (int k = aSize - 1; k != i; k--) {
 | 
|---|
| 478 |                 mpn_random(&newKey.key[k], 1);
 | 
|---|
| 479 |         }
 | 
|---|
| 480 |         newKey.trim();
 | 
|---|
| 481 | 
 | 
|---|
| 482 |         return newKey;
 | 
|---|
| 483 | }
 | 
|---|
| 484 | 
 | 
|---|
| 485 | // calculate shared prefix length
 | 
|---|
| 486 | uint Identifier::sharedPrefixLength(const Identifier& compKey) const {
 | 
|---|
| 487 |         if (compareTo(compKey) == 0) return keyLength;
 | 
|---|
| 488 | 
 | 
|---|
| 489 |         uint length = 0;
 | 
|---|
| 490 |         int i;
 | 
|---|
| 491 |         uint j;
 | 
|---|
| 492 |         bool msb = true;
 | 
|---|
| 493 | 
 | 
|---|
| 494 |         // count equal limbs first:
 | 
|---|
| 495 |         for (i = aSize - 1; i >= 0; --i) {
 | 
|---|
| 496 |                 if (this->key[i] != compKey.key[i]) {
 | 
|---|
| 497 |                         // XOR first differing limb for easy counting of the bits:
 | 
|---|
| 498 |                         mp_limb_t d = this->key[i] ^ compKey.key[i];
 | 
|---|
| 499 |                         if (msb) d <<= (GMP_LIMB_BITS - (keyLength % GMP_LIMB_BITS));
 | 
|---|
| 500 |                         for (j = GMP_LIMB_BITS - 1; d >>= 1; --j)
 | 
|---|
| 501 |                                 ;
 | 
|---|
| 502 |                         length += j;
 | 
|---|
| 503 |                         break;
 | 
|---|
| 504 |                 }
 | 
|---|
| 505 |                 length += GMP_LIMB_BITS;
 | 
|---|
| 506 |                 msb = false;
 | 
|---|
| 507 |         }
 | 
|---|
| 508 | 
 | 
|---|
| 509 |         return length;
 | 
|---|
| 510 | }
 | 
|---|
| 511 | 
 | 
|---|
| 512 | // calculate log of base 2
 | 
|---|
| 513 | int Identifier::log_2() const {
 | 
|---|
| 514 |         int16_t i = aSize - 1;
 | 
|---|
| 515 | 
 | 
|---|
| 516 |         while (i >= 0 && key[i] == 0) {
 | 
|---|
| 517 |                 i--;
 | 
|---|
| 518 |         }
 | 
|---|
| 519 | 
 | 
|---|
| 520 |         if (i < 0) {
 | 
|---|
| 521 |                 return -1;
 | 
|---|
| 522 |         }
 | 
|---|
| 523 | 
 | 
|---|
| 524 |         mp_limb_t j = key[i];
 | 
|---|
| 525 |         i *= GMP_LIMB_BITS;
 | 
|---|
| 526 |         while (j != 0) {
 | 
|---|
| 527 |                 j >>= 1;
 | 
|---|
| 528 |                 i++;
 | 
|---|
| 529 |         }
 | 
|---|
| 530 | 
 | 
|---|
| 531 |         return i - 1;
 | 
|---|
| 532 | }
 | 
|---|
| 533 | 
 | 
|---|
| 534 | // returns a simple hash of the key
 | 
|---|
| 535 | size_t Identifier::hash() const {
 | 
|---|
| 536 |         return (size_t) key[0];
 | 
|---|
| 537 | }
 | 
|---|
| 538 | 
 | 
|---|
| 539 | // returns true, if this key is element of the interval (keyA, keyB)
 | 
|---|
| 540 | bool Identifier::isBetween(const Identifier& keyA, const Identifier& keyB) const {
 | 
|---|
| 541 |         if (isUnspec || keyA.isUnspec || keyB.isUnspec) return false;
 | 
|---|
| 542 | 
 | 
|---|
| 543 |         if (*this == keyA) return false;
 | 
|---|
| 544 |         else if (keyA < keyB) return ((*this > keyA) && (*this < keyB));
 | 
|---|
| 545 |         else return ((*this > keyA) || (*this < keyB));
 | 
|---|
| 546 | }
 | 
|---|
| 547 | 
 | 
|---|
| 548 | // returns true, if this key is element of the interval (keyA, keyB]
 | 
|---|
| 549 | bool Identifier::isBetweenR(const Identifier& keyA, const Identifier& keyB) const {
 | 
|---|
| 550 |         if (isUnspec || keyA.isUnspec || keyB.isUnspec) return false;
 | 
|---|
| 551 | 
 | 
|---|
| 552 |         if ((keyA == keyB) && (*this == keyA)) return true;
 | 
|---|
| 553 |         else if (keyA <= keyB) return ((*this > keyA) && (*this <= keyB));
 | 
|---|
| 554 |         else return ((*this > keyA) || (*this <= keyB));
 | 
|---|
| 555 | }
 | 
|---|
| 556 | 
 | 
|---|
| 557 | // returns true, if this key is element of the interval [keyA, keyB)
 | 
|---|
| 558 | bool Identifier::isBetweenL(const Identifier& keyA, const Identifier& keyB) const {
 | 
|---|
| 559 |         if (isUnspec || keyA.isUnspec || keyB.isUnspec) return false;
 | 
|---|
| 560 | 
 | 
|---|
| 561 |         if ((keyA == keyB) && (*this == keyA)) return true;
 | 
|---|
| 562 |         else if (keyA <= keyB) return ((*this >= keyA) && (*this < keyB));
 | 
|---|
| 563 |         else return ((*this >= keyA) || (*this < keyB));
 | 
|---|
| 564 | }
 | 
|---|
| 565 | 
 | 
|---|
| 566 | // returns true, if this key is element of the interval [keyA, keyB]
 | 
|---|
| 567 | bool Identifier::isBetweenLR(const Identifier& keyA, const Identifier& keyB) const {
 | 
|---|
| 568 |         if (isUnspec || keyA.isUnspec || keyB.isUnspec) return false;
 | 
|---|
| 569 | 
 | 
|---|
| 570 |         if ((keyA == keyB) && (*this == keyA)) return true;
 | 
|---|
| 571 |         else if (keyA <= keyB) return ((*this >= keyA) && (*this <= keyB));
 | 
|---|
| 572 |         else return ((*this >= keyA) || (*this <= keyB));
 | 
|---|
| 573 | }
 | 
|---|
| 574 | 
 | 
|---|
| 575 | //----------------------------------------------------------------------
 | 
|---|
| 576 | // statics and globals
 | 
|---|
| 577 | //----------------------------------------------------------------------
 | 
|---|
| 578 | 
 | 
|---|
| 579 | // default console output
 | 
|---|
| 580 | std::ostream& operator<<(std::ostream& os, const Identifier& c) {
 | 
|---|
| 581 |         os << c.toString(16);
 | 
|---|
| 582 |         return os;
 | 
|---|
| 583 | }
 | 
|---|
| 584 | ;
 | 
|---|
| 585 | 
 | 
|---|
| 586 | // returns a key filled with bit 1
 | 
|---|
| 587 | Identifier Identifier::max() {
 | 
|---|
| 588 |         Identifier newKey;
 | 
|---|
| 589 | 
 | 
|---|
| 590 |         for (uint i = 0; i < aSize; i++) {
 | 
|---|
| 591 |                 newKey.key[i] = ~0;
 | 
|---|
| 592 |         }
 | 
|---|
| 593 |         newKey.isUnspec = false;
 | 
|---|
| 594 |         newKey.trim();
 | 
|---|
| 595 | 
 | 
|---|
| 596 |         return newKey;
 | 
|---|
| 597 | }
 | 
|---|
| 598 | 
 | 
|---|
| 599 | // generate random number
 | 
|---|
| 600 | Identifier Identifier::random() {
 | 
|---|
| 601 |         Identifier newKey = ZERO;
 | 
|---|
| 602 |         newKey.clearAddress();
 | 
|---|
| 603 | 
 | 
|---|
| 604 |         //as mpn_random has no seeding function
 | 
|---|
| 605 |         // we mess aroung here a little to achive some randomness
 | 
|---|
| 606 |         // using the rand function that _is_ seeded in the
 | 
|---|
| 607 |         // StartupWrapper::initSystem function
 | 
|---|
| 608 | 
 | 
|---|
| 609 |         Identifier keyRandom = ZERO;
 | 
|---|
| 610 |         mpn_random(keyRandom.key, aSize);
 | 
|---|
| 611 |         Identifier keyrnd( rand() );
 | 
|---|
| 612 |         mpn_mul_1( newKey.key, keyRandom.key, aSize, *keyrnd.key );
 | 
|---|
| 613 | 
 | 
|---|
| 614 |         newKey.trim();
 | 
|---|
| 615 |         assert(!newKey.isUnspecified());
 | 
|---|
| 616 | 
 | 
|---|
| 617 |         return newKey;
 | 
|---|
| 618 | }
 | 
|---|
| 619 | 
 | 
|---|
| 620 | Identifier Identifier::sha1(const string& input) {
 | 
|---|
| 621 |         Identifier newKey;
 | 
|---|
| 622 |         newKey.clearAddress();
 | 
|---|
| 623 |         uint8_t temp[40];
 | 
|---|
| 624 |         for (int i=0; i<40; i++) temp[i] = 0;
 | 
|---|
| 625 |         const char* c_str = input.c_str();
 | 
|---|
| 626 | 
 | 
|---|
| 627 |         CSHA1 sha;
 | 
|---|
| 628 |         sha.Reset();
 | 
|---|
| 629 |         sha.Update( (uint8_t*)c_str, (uint32_t)input.size() );
 | 
|---|
| 630 |         sha.Final();
 | 
|---|
| 631 |         sha.GetHash(temp);
 | 
|---|
| 632 |         mpn_set_str(newKey.key, (const uint8_t*)temp,
 | 
|---|
| 633 |                                  (int)aSize * sizeof(mp_limb_t), 256);
 | 
|---|
| 634 |         newKey.isUnspec = false;
 | 
|---|
| 635 |         newKey.trim();
 | 
|---|
| 636 | 
 | 
|---|
| 637 |         return newKey;
 | 
|---|
| 638 | }
 | 
|---|
| 639 | 
 | 
|---|
| 640 | Identifier Identifier::sha1(const uint8_t* value, size_t length ) {
 | 
|---|
| 641 |         Identifier newKey;
 | 
|---|
| 642 |         uint8_t temp[40];
 | 
|---|
| 643 |         for (int i=0; i<40; i++) temp[i] = 0;
 | 
|---|
| 644 | 
 | 
|---|
| 645 |         CSHA1 sha;
 | 
|---|
| 646 |         sha.Reset();
 | 
|---|
| 647 |         sha.Update( const_cast<uint8_t*>(value), (uint32_t)length );
 | 
|---|
| 648 |         sha.Final();
 | 
|---|
| 649 |         sha.GetHash(temp);
 | 
|---|
| 650 |         mpn_set_str( newKey.key, (const uint8_t*)temp, (int)aSize * sizeof(mp_limb_t), 256);
 | 
|---|
| 651 |         newKey.isUnspec = false;
 | 
|---|
| 652 |         newKey.trim();
 | 
|---|
| 653 |         return newKey;
 | 
|---|
| 654 | }
 | 
|---|
| 655 | 
 | 
|---|
| 656 | // generate a key=2**exponent
 | 
|---|
| 657 | Identifier Identifier::pow2(uint exponent) {
 | 
|---|
| 658 |         Identifier newKey = ZERO;
 | 
|---|
| 659 | 
 | 
|---|
| 660 |         newKey.key[exponent / GMP_LIMB_BITS] = (mp_limb_t) 1 << (exponent
 | 
|---|
| 661 |                         % GMP_LIMB_BITS);
 | 
|---|
| 662 | 
 | 
|---|
| 663 |         return newKey;
 | 
|---|
| 664 | }
 | 
|---|
| 665 | 
 | 
|---|
| 666 | //--------------------------------------------------------------------
 | 
|---|
| 667 | // private methods (mostly inlines)
 | 
|---|
| 668 | //--------------------------------------------------------------------
 | 
|---|
| 669 | 
 | 
|---|
| 670 | // trims a key after each operation
 | 
|---|
| 671 | inline void Identifier::trim() {
 | 
|---|
| 672 |         key[array_size] = ~0;
 | 
|---|
| 673 |         key[array_size - 1] &= GMP_MSB_MASK;
 | 
|---|
| 674 | }
 | 
|---|
| 675 | 
 | 
|---|
| 676 | // compares this key to any other
 | 
|---|
| 677 | int Identifier::compareTo(const Identifier& compKey) const {
 | 
|---|
| 678 | 
 | 
|---|
| 679 |         if( compKey.isUnspec == false && isUnspec == false )
 | 
|---|
| 680 |                 return mpn_cmp( key, compKey.key, aSize );
 | 
|---|
| 681 |         else if( compKey.isUnspec == true && isUnspec == true )
 | 
|---|
| 682 |                 return 0;
 | 
|---|
| 683 |         else
 | 
|---|
| 684 |                 return -1;
 | 
|---|
| 685 | }
 | 
|---|
| 686 | 
 | 
|---|
| 687 | }} // namespace ariba, common
 | 
|---|