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
|
---|