00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _terimber_common_hpp_
00029 #define _terimber_common_hpp_
00030
00031 #include "base/common.h"
00032 #include "base/except.h"
00033 #include "base/string.hpp"
00034
00035 BEGIN_TERIMBER_NAMESPACE
00036 #pragma pack(4)
00037
00038
00040 const ub1_t _ch_period = '.';
00042 const ub1_t _ch0 = '0';
00044 const ub1_t _ch1 = '1';
00046 const ub1_t _ch7 = '7';
00048 const ub1_t _ch9 = '9';
00050 const ub1_t _chA = 'A';
00052 const ub1_t _cha = 'a';
00054 const ub1_t _chF = 'F';
00056 const ub1_t _chf = 'f';
00057
00058
00059 inline
00060 void*
00061 check_pointer(void* ptr)
00062 {
00063 if (!ptr)
00064 exception::_throw("Not enough memory");
00065 return ptr;
00066 }
00067
00068 inline
00069 size_t
00070 get8bits(unsigned char x)
00071 {
00072 return (size_t)tolower(x);
00073 }
00074
00075 inline
00076 size_t
00077 get16bits(const unsigned char* x)
00078 {
00079 return (size_t)tolower(x[0]) + (size_t)(tolower(x[1]) << 8);
00080 }
00081
00082 template < class T >
00083 inline
00084 size_t
00085 do_hash(const T* x, size_t len)
00086 {
00087 if (!len || !x)
00088 return 0;
00089
00090
00091 if (len == os_minus_one)
00092 len = str_template::strlen(x);
00093
00094 const unsigned char* ptr = (unsigned char*)x;
00095 size_t hash = len;
00096 size_t rem = len & 3;
00097 len >>= 2;
00098
00099
00100 for (; len > 0; --len)
00101 {
00102 hash += get16bits(ptr);
00103 size_t tmp = (get16bits(ptr + 2) << 11) ^ hash;
00104 hash += ((hash << 16) ^ tmp) >> 11;
00105 ptr += 4;
00106 }
00107
00108
00109 switch (rem)
00110 {
00111 case 3:
00112 hash += get16bits(ptr);
00113 hash ^= hash << 16;
00114 hash ^= get8bits(ptr[2]) << 18;
00115 hash += hash >> 11;
00116 break;
00117 case 2:
00118 hash += get16bits(ptr);
00119 hash ^= hash << 11;
00120 hash += hash >> 17;
00121 break;
00122 case 1:
00123 hash += get8bits(ptr[0]);
00124 hash ^= hash << 10;
00125 hash += hash >> 1;
00126 }
00127
00128
00129 hash ^= hash << 3;
00130 hash += hash >> 5;
00131 hash ^= hash << 4;
00132 hash += hash >> 17;
00133 hash ^= hash << 25;
00134 hash += hash >> 6;
00135
00136 return hash;
00137 }
00138
00139 template < class T >
00140 inline
00141 T*
00142 copy_string(const T* x, byte_allocator& _allocator, size_t len)
00143 {
00144 T* dest = 0;
00145 if (!x)
00146 return 0;
00147
00148 len = (len == os_minus_one) ? str_template::strlen(x) : len;
00149 dest = (T*)_allocator.allocate((len + 1) * sizeof(T));
00150 if (dest)
00151 {
00152 memcpy(dest, x, len * sizeof(T));
00153 dest[len] = 0;
00154 }
00155
00156 return dest;
00157 }
00158
00159 template < class T >
00160 inline
00161 bool
00162 hex_to_binary(ub1_t* dest, const T* x, size_t len)
00163 {
00164 if (!dest)
00165 return false;
00166
00167 *(size_t*)dest = 0;
00168
00169
00170 len = (len == os_minus_one) ? (x ? strlen(x) : 0) : len;
00171
00172 if (!len)
00173 return false;
00174
00175
00176 ub1_t* buf = dest + sizeof(size_t);
00177
00178 size_t index = 0;
00179 for (; index < len / 2; ++index)
00180 {
00181 if (!hex_to_byte(*buf, x, RADIX16))
00182 return false;
00183 ++buf;
00184 x += 2;
00185 }
00186
00187
00188 *(size_t*)dest = index;
00189 return true;
00190 }
00191
00192 template < class T >
00193 inline
00194 bool
00195 symbol_to_byte(ub1_t &dest, T x, numeric_radix radix_)
00196 {
00197 switch (radix_)
00198 {
00199 case RADIX16:
00200 if (x >= _ch0 && x <= _ch9)
00201 dest = x - _ch0;
00202 else if (x >= _chA && x <= _chF)
00203 dest = x - _chA + 0x0A;
00204 else if (x >= _cha && x <= _chf)
00205 dest = x - _cha + 0x0A;
00206 else
00207 return false;
00208 break;
00209 case RADIX2:
00210 if (x >= _ch0 && x <= _ch1)
00211 dest = x - _ch0;
00212 else
00213 return false;
00214 break;
00215 case RADIX8:
00216 if (x >= _ch0 && x <= _ch7)
00217 dest = x - _ch0;
00218 else
00219 return false;
00220 break;
00221 case RADIX10:
00222 if (x >= _ch0 && x <= _ch9)
00223 dest = x - _ch0;
00224 else
00225 return false;
00226 break;
00227 }
00228
00229 return true;
00230 }
00231
00232 template < class T >
00233 inline
00234 bool
00235 hex_to_byte(ub1_t &dest, const T* x, numeric_radix radix_)
00236 {
00237 if (!x)
00238 return false;
00239
00240 ub1_t uplimit = 0;
00241 switch (radix_)
00242 {
00243 case RADIX16:
00244 uplimit = 2;
00245 break;
00246 case RADIX2:
00247 uplimit = 8;
00248 break;
00249 case RADIX8:
00250 uplimit = 4;
00251 break;
00252 case RADIX10:
00253 uplimit = 3;
00254 break;
00255 }
00256
00257 dest = 0;
00258 for (ub1_t index = 0; index < uplimit; ++index)
00259 {
00260 dest *= radix_;
00261 ub1_t dummy = 0;
00262 if (symbol_to_byte(dummy, x[index], radix_))
00263 dest += dummy;
00264 else
00265 return false;
00266 }
00267
00268 return true;
00269 }
00270
00271 template < class T >
00272 inline
00273 void
00274 binary_to_hex(T* dest, const ub1_t* x)
00275 {
00276 if (!dest || !x)
00277 return;
00278
00279 *dest = 0;
00280
00281
00282 size_t len = *(size_t*)x;
00283 dest[2 * len] = 0;
00284 const ub1_t* buf = x + sizeof(size_t);
00285
00286 for (size_t index = 0; index < len; ++index)
00287 {
00288 byte_to_hex(dest, *buf);
00289 ++buf;
00290 dest += 2;
00291 }
00292 }
00293
00294 template < class T >
00295 inline
00296 void
00297 byte_to_symbol(T& dest, ub1_t x)
00298 {
00299 dest = (x & 0x0F) < 0x0A ? _ch0 + (x & 0x0F) : _chA + ((x - 0x0A) & 0x0F);
00300 }
00301
00302 template < class T >
00303 inline
00304 void
00305 byte_to_hex(T* dest, ub1_t x)
00306 {
00307 assert(dest);
00308 byte_to_symbol(dest[1], x);
00309 x >>= 4;
00310 byte_to_symbol(dest[0], x);
00311 }
00312
00313 template < class T >
00314 inline
00315 T*
00316 guid_to_string(T* dest, const guid_t& x)
00317 {
00318 assert(dest);
00319 T* retVal = dest;
00320 byte_to_hex(dest, (ub1_t)((0xff000000 & x.Data1) >> 24));
00321 dest += 2;
00322 byte_to_hex(dest, (ub1_t)((0x00ff0000 & x.Data1) >> 16));
00323 dest += 2;
00324 byte_to_hex(dest, (ub1_t)((0x0000ff00 & x.Data1) >> 8));
00325 dest += 2;
00326 byte_to_hex(dest, (ub1_t)(0x000000ff & x.Data1));
00327 dest += 2;
00328
00329 byte_to_hex(dest, (ub1_t)((0xff00 & x.Data2) >> 8));
00330 dest += 2;
00331 byte_to_hex(dest, (ub1_t)(0x00ff & x.Data2));
00332 dest += 2;
00333
00334 byte_to_hex(dest, (ub1_t)((0xff00 & x.Data3) >> 8));
00335 dest += 2;
00336 byte_to_hex(dest, (ub1_t)(0x00ff & x.Data3));
00337 dest += 2;
00338
00339 for (size_t index = 0; index < 8; ++index)
00340 {
00341 byte_to_hex(dest, x.Data4[index]);
00342 dest += 2;
00343 }
00344
00345 *dest = 0;
00346
00347 return retVal;
00348 }
00349
00350 template < class T >
00351 inline
00352 bool
00353 string_to_guid(guid_t& dest, const T* x)
00354 {
00355 ub1_t b1, b2, b3, b4;
00356
00357 memset(&dest, 0, sizeof(guid_t));
00358 if (!x)
00359 return false;
00360 if (!hex_to_byte(b1, x, RADIX16))
00361 return false;
00362 x += 2;
00363 if (!hex_to_byte(b2, x, RADIX16))
00364 return false;
00365 x += 2;
00366 if (!hex_to_byte(b3, x, RADIX16))
00367 return false;
00368 x += 2;
00369 if (!hex_to_byte(b4, x, RADIX16))
00370 return false;
00371
00372 dest.Data1 = (ub4_t)(b1 << 24) |
00373 (ub4_t)(b2 << 16) |
00374 (ub4_t)(b3 << 8) |
00375 (ub4_t)b4;
00376
00377 x += 2;
00378 if (!hex_to_byte(b1, x, RADIX16))
00379 return false;
00380 x += 2;
00381 if (!hex_to_byte(b2, x, RADIX16))
00382 return false;
00383
00384 dest.Data2 = (ub2_t)(b1 << 8) |
00385 (ub2_t)b2;
00386
00387 x += 2;
00388 if (!hex_to_byte(b1, x, RADIX16))
00389 return false;
00390 x += 2;
00391 if (!hex_to_byte(b2, x, RADIX16))
00392 return false;
00393
00394 dest.Data3 = (ub2_t)(b1 << 8) |
00395 (ub2_t)b2;
00396
00397 for (size_t index = 0; index < 8; ++index)
00398 {
00399 x += 2;
00400 if (!hex_to_byte(dest.Data4[index], x, RADIX16))
00401 return false;
00402 }
00403
00404 return true;
00405 }
00406
00407 template < class T >
00408 inline
00409 int
00410 simple_compare(const T& v1, const T& v2)
00411 {
00412 return v1 != v2 ? (v1 < v2 ? -1 : 1 ) : 0;
00413 }
00414
00415 template < class T >
00416 inline
00417 int
00418 memory_compare(const T& v1, const T& v2)
00419 {
00420 return !v1 ? (!v2 ? 0 : -1) : (!v2 ? 1 : memcmp(v1, v2, sizeof(T)));
00421 }
00422
00423 inline
00424 int
00425 memory_compare_binary(const size_t* v1, const size_t* v2)
00426 {
00427 return !v1 ? (!v2 ? 0 : -1) : (!v2 ? 1 : memcmp(v1 + 1, v2 + 1, __min(*v1, *v2)));
00428 }
00429
00430 template < class T >
00431 inline
00432 int
00433 simple_compare_ptr(const T* v1, const T* v2)
00434 {
00435 return !v1 ? (!v2 ? 0 : -1) : (!v2 ? 1 : simple_compare(*v1, *v2));
00436 }
00437
00438 template < class T, class F >
00439 inline
00440 int
00441 string_compare(const T& v1, const T& v2, F fn)
00442 {
00443 return !v1 ? (!v2 ? 0 : -1) : (!v2 ? 1 : fn(v1, v2));
00444 }
00445
00446 inline
00447 size_t
00448 do_hash(vt_types type, const terimber_xml_value& x)
00449 {
00450 size_t res = 0;
00451
00452 switch(type)
00453 {
00454 case vt_binary:
00455 {
00456 size_t len = x.bufVal ? *(size_t*)x.bufVal : 0;
00457 const char* ptr = len ? ((const char*)x.bufVal + sizeof(size_t)) : 0;
00458 res = do_hash(ptr, len);
00459 }
00460 break;
00461 case vt_string:
00462 do_hash(x.strVal, os_minus_one);
00463 break;
00464 case vt_wstring:
00465 do_hash(x.wstrVal, os_minus_one);
00466 break;
00467 default:
00468 break;
00469 }
00470
00471 return res;
00472 }
00473
00474 inline
00475 int
00476 compare_value(vt_types type, const terimber_xml_value& first, const terimber_xml_value& second, bool use_hash, bool case_insensitive)
00477 {
00478 switch(type)
00479 {
00480 case vt_empty:
00481 case vt_null:
00482 return 0;
00483 case vt_bool:
00484 return simple_compare(first.boolVal, second.boolVal);
00485 case vt_sb1:
00486 return simple_compare(first.cVal, second.cVal);
00487 case vt_ub1:
00488 return simple_compare(first.bVal, second.bVal);
00489 case vt_sb2:
00490 return simple_compare(first.iVal, second.iVal);
00491 case vt_ub2:
00492 return simple_compare(first.uiVal, second.uiVal);
00493 case vt_sb4:
00494 return simple_compare(first.lVal, second.lVal);
00495 case vt_ub4:
00496 return simple_compare(first.ulVal, second.ulVal);
00497 case vt_float:
00498 return simple_compare(first.fltVal, second.fltVal);
00499 case vt_double:
00500 case vt_date:
00501 #ifdef OS_64BIT
00502 return simple_compare(first.dblVal, second.dblVal);
00503 #else
00504 return simple_compare_ptr(first.dblVal, second.dblVal);
00505 #endif
00506 case vt_guid:
00507 return memory_compare(first.guidVal, second.guidVal);
00508 case vt_sb8:
00509 #ifdef OS_64BIT
00510 return simple_compare(first.intVal, second.intVal);
00511 #else
00512 return simple_compare_ptr(first.intVal, second.intVal);
00513 #endif
00514 case vt_ub8:
00515 #ifdef OS_64BIT
00516 return simple_compare(first.uintVal, second.uintVal);
00517 #else
00518 return simple_compare_ptr(first.uintVal, second.uintVal);
00519 #endif
00520 case vt_binary:
00521 return memory_compare_binary((const size_t*)first.bufVal, (const size_t*)second.bufVal);
00522 case vt_string:
00523 return use_hash ? simple_compare(first.lVal, second.lVal) : (case_insensitive ? str_template::strnocasecmp(first.strVal, second.strVal, os_minus_one) : str_template::strcmp(first.strVal, second.strVal, os_minus_one));
00524 case vt_wstring:
00525 return use_hash ? simple_compare(first.lVal, second.lVal) : (case_insensitive ? str_template::strnocasecmp(first.wstrVal, second.wstrVal, os_minus_one) : str_template::strcmp(first.wstrVal, second.wstrVal, os_minus_one));
00526 default:
00527 return -1;
00528 }
00529 }
00530
00531 inline
00532 terimber_xml_value
00533 copy_value(vt_types type, const terimber_xml_value& x, byte_allocator& _allocator)
00534 {
00535 terimber_xml_value dest;
00536 memset(&dest, 0, sizeof(terimber_xml_value));
00537
00538 switch(type)
00539 {
00540 case vt_empty:
00541 case vt_null:
00542 case vt_bool:
00543 case vt_sb1:
00544 case vt_ub1:
00545 case vt_sb2:
00546 case vt_ub2:
00547 case vt_sb4:
00548 case vt_ub4:
00549 case vt_float:
00550 memcpy(&dest, &x, sizeof(terimber_xml_value));
00551 break;
00552 case vt_double:
00553 if (x.dblVal)
00554 {
00555 #ifdef OS_64BIT
00556 dest.dblVal = x.dblVal;
00557 #else
00558 double* dummy = 0;
00559 dummy = (double*)check_pointer(_allocator.allocate(sizeof(double)));
00560 *dummy = *x.dblVal;
00561 dest.dblVal = dummy;
00562 #endif
00563 }
00564 break;
00565 case vt_guid:
00566 if (x.guidVal)
00567 {
00568 guid_t* dummy = (guid_t*)check_pointer(_allocator.allocate(sizeof(guid_t)));
00569 *dummy = *x.guidVal;
00570 dest.guidVal = dummy;
00571 }
00572 break;
00573 case vt_sb8:
00574 case vt_date:
00575 if (x.intVal)
00576 {
00577 #ifdef OS_64BIT
00578 dest.intVal = x.intVal;
00579 #else
00580 sb8_t* dummy = (sb8_t*)check_pointer(_allocator.allocate(sizeof(sb8_t)));
00581 memcpy(dummy, x.intVal, sizeof(sb8_t));
00582 dest.intVal = dummy;
00583 #endif
00584 }
00585 break;
00586 case vt_ub8:
00587 if (x.uintVal)
00588 {
00589 #ifdef OS_64BIT
00590 dest.uintVal = x.uintVal;
00591 #else
00592 ub8_t* dummy = (ub8_t*)check_pointer(_allocator.allocate(sizeof(ub8_t)));
00593 memcpy(dummy, x.uintVal, sizeof(ub8_t));
00594 dest.uintVal = dummy;
00595 #endif
00596 }
00597 break;
00598 case vt_binary:
00599 if (x.bufVal)
00600 {
00601 size_t len = *(size_t*)x.bufVal;
00602 ub1_t* dummy = (ub1_t*)check_pointer(_allocator.allocate(len + sizeof(size_t)));
00603
00604 *(size_t*)dummy = len;
00605 if (len)
00606 memcpy(dummy + sizeof(size_t), x.bufVal + sizeof(size_t), len);
00607
00608 dest.bufVal = dummy;
00609 }
00610 break;
00611 case vt_decimal:
00612 case vt_numeric:
00613 case vt_string:
00614 if (x.strVal)
00615 dest.strVal = copy_string(x.strVal, _allocator, os_minus_one);
00616 break;
00617 case vt_wstring:
00618 if (x.wstrVal)
00619 dest.wstrVal = copy_string(x.wstrVal, _allocator, os_minus_one);
00620 break;
00621 default:
00622 assert(false);
00623 break;
00624 }
00625
00626 return dest;
00627 }
00628
00630 inline
00631 bool
00632 operator==(const guid_t& first, const guid_t& second)
00633 {
00634 return memcmp(&first, &second, sizeof(guid_t)) == 0;
00635 }
00636
00637 inline
00638 bool
00639 operator!=(const guid_t& first, const guid_t& second)
00640 {
00641 return memcmp(&first, &second, sizeof(guid_t)) != 0;
00642 }
00643
00644 inline
00645 bool
00646 operator<(const guid_t& first, const guid_t& second)
00647 {
00648 return memcmp(&first, &second, sizeof(guid_t)) < 0;
00649 }
00650
00651 inline bool operator>(const guid_t& first, const guid_t& second)
00652 { return memcmp(&first, &second, sizeof(guid_t)) > 0; }
00653
00655
00656 inline
00657 paged_buffer&
00658 paged_buffer::operator<<(ub1_t symbol)
00659 {
00660 if (_pos == _size)
00661 add_page();
00662
00663 _ptr[_pos++] = symbol;
00664
00665 return *this;
00666 }
00667
00668
00669 inline
00670 paged_buffer&
00671 paged_buffer::operator<<(const char* x)
00672 {
00673 while (*x)
00674 {
00675 if (_pos == _size)
00676 add_page();
00677 _ptr[_pos++] = *x++;
00678 }
00679
00680 return *this;
00681 }
00682
00683
00684 inline
00685 paged_buffer&
00686 paged_buffer::append(const ub1_t* x, size_t size)
00687 {
00688 size_t len;
00689 while (size)
00690 {
00691 if (_pos == _size)
00692 add_page();
00693 else
00694 {
00695 len = __min(size, _size - _pos);
00696 memcpy(_ptr + _pos, x, len);
00697 size -= len;
00698 _pos += len;
00699 x += len;
00700 }
00701 }
00702
00703 return *this;
00704 }
00705
00706
00707 inline
00708 const char*
00709 paged_buffer::persist()
00710 {
00711
00712 if (_buffer.empty())
00713 {
00714 _primary[_pos] = 0;
00715 return (const char*)_primary;
00716 }
00717 else
00718 return _persist();
00719
00720 }
00721
00722
00723 inline
00724 const ub1_t*
00725 paged_buffer::persist(size_t& size_)
00726 {
00727
00728 if (_buffer.empty())
00729 {
00730 size_ = _pos;
00731 return _primary;
00732 }
00733 else
00734 return _persist(size_);
00735 }
00736
00737
00738
00739
00740 inline
00741 void
00742 paged_buffer::reset()
00743 {
00744 _pos = 0;
00745 _buffer.clear();
00746 _ptr = _primary;
00747 }
00748
00749
00750 inline
00751 size_t
00752 paged_buffer::size() const
00753 {
00754 if (_buffer.empty())
00755 return _pos;
00756 else
00757 {
00758 size_t retVal = _size;
00759 for (paged_store_t::const_iterator iter = _buffer.begin(); iter != _buffer.end(); ++iter)
00760 {
00761 retVal += (iter != --_buffer.end()) ? _size : _pos;
00762 }
00763 return retVal;
00764 }
00765 }
00766
00767
00768 inline
00769 byte_allocator&
00770 paged_buffer::get_tmp_allocator()
00771 {
00772 return _tmp_allocator;
00773 }
00774
00775 inline
00776 size_t
00777 paged_buffer::get_page_size() const
00778 {
00779 return _size;
00780 }
00781
00782 #pragma pack()
00783 END_TERIMBER_NAMESPACE
00784
00785 #endif // _terimber_common_hpp_
00786