|
reSIProcate/rutil
9694
|
00001 #include <algorithm> 00002 #include <cassert> 00003 #include <ctype.h> 00004 #include <math.h> 00005 #include <limits.h> 00006 00007 #if defined(HAVE_CONFIG_H) 00008 #include "config.h" 00009 #endif 00010 00011 #include "rutil/Data.hxx" 00012 #include "rutil/ParseBuffer.hxx" 00013 #include "rutil/vmd5.hxx" 00014 #include "rutil/Coders.hxx" 00015 #include "rutil/WinLeakCheck.hxx" 00016 00017 #ifdef WIN32 00018 #include "Winsock2.h" 00019 #endif 00020 00021 using namespace resip; 00022 using namespace std; 00023 00024 const Data Data::Empty("", 0); 00025 const Data::size_type Data::npos = UINT_MAX; 00026 00027 Data::PreallocateType::PreallocateType(int) 00028 {} 00029 00030 const Data::PreallocateType Data::Preallocate(0); 00031 00032 const bool DataHelper::isCharHex[256] = 00033 { 00034 // 0 1 2 3 4 5 6 7 8 9 a b c d e f 00035 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //0 00036 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //1 00037 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //2 00038 true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, //3 00039 false, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, //4 00040 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //5 00041 false, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, //6 00042 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //8 00043 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //9 00044 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //a 00045 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //b 00046 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //c 00047 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //d 00048 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, //e 00049 false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false //f 00050 }; 00051 00052 //must be lowercase for MD5 00053 static const char hexmap[] = "0123456789abcdef"; 00054 00055 int 00056 hexpair2int(char high, char low) 00057 { 00058 int val; 00059 00060 switch(high) 00061 { 00062 case '0': 00063 val = 0x00; 00064 break; 00065 case '1': 00066 val = 0x10; 00067 break; 00068 case '2': 00069 val = 0x20; 00070 break; 00071 case '3': 00072 val = 0x30; 00073 break; 00074 case '4': 00075 val = 0x40; 00076 break; 00077 case '5': 00078 val = 0x50; 00079 break; 00080 case '6': 00081 val = 0x60; 00082 break; 00083 case '7': 00084 val = 0x70; 00085 break; 00086 case '8': 00087 val = 0x80; 00088 break; 00089 case '9': 00090 val = 0x90; 00091 break; 00092 case 'A': 00093 case 'a': 00094 val = 0xA0; 00095 break; 00096 case 'B': 00097 case 'b': 00098 val = 0xB0; 00099 break; 00100 case 'C': 00101 case 'c': 00102 val = 0xC0; 00103 break; 00104 case 'D': 00105 case 'd': 00106 val = 0xD0; 00107 break; 00108 case 'E': 00109 case 'e': 00110 val = 0xE0; 00111 break; 00112 case 'F': 00113 case 'f': 00114 val = 0xF0; 00115 break; 00116 default: 00117 return '?'; 00118 break; 00119 } 00120 00121 switch(low) 00122 { 00123 case '0': 00124 if (!val) 00125 { 00126 return '?'; 00127 } 00128 break; 00129 case '1': 00130 val += 0x01; 00131 break; 00132 case '2': 00133 val += 0x02; 00134 break; 00135 case '3': 00136 val += 0x03; 00137 break; 00138 case '4': 00139 val += 0x04; 00140 break; 00141 case '5': 00142 val += 0x05; 00143 break; 00144 case '6': 00145 val += 0x06; 00146 break; 00147 case '7': 00148 val += 0x07; 00149 break; 00150 case '8': 00151 val += 0x08; 00152 break; 00153 case '9': 00154 val += 0x09; 00155 break; 00156 case 'A': 00157 case 'a': 00158 val += 0x0A; 00159 break; 00160 case 'B': 00161 case 'b': 00162 val += 0x0B; 00163 break; 00164 case 'C': 00165 case 'c': 00166 val += 0x0C; 00167 break; 00168 case 'D': 00169 case 'd': 00170 val += 0x0D; 00171 break; 00172 case 'E': 00173 case 'e': 00174 val += 0x0E; 00175 break; 00176 case 'F': 00177 case 'f': 00178 val += 0x0F; 00179 break; 00180 default: 00181 return '?'; 00182 break; 00183 } 00184 return val; 00185 } 00186 00187 bool 00188 Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE> arg) 00189 { 00190 return true; 00191 } 00192 00193 Data::Data(size_type capacity, 00194 const Data::PreallocateType&) 00195 : mBuf(capacity > LocalAlloc 00196 ? new char[capacity + 1] 00197 : mPreBuffer), 00198 mSize(0), 00199 mCapacity(capacity > LocalAlloc 00200 ? capacity 00201 : LocalAlloc), 00202 mShareEnum(capacity > LocalAlloc ? Take : Borrow) 00203 { 00204 assert( capacity >= 0 ); 00205 mBuf[mSize] = 0; 00206 } 00207 00208 #ifdef DEPRECATED_PREALLOC 00209 // pre-allocate capacity 00210 Data::Data(size_type capacity, bool) 00211 : mBuf(capacity > LocalAlloc 00212 ? new char[capacity + 1] 00213 : mPreBuffer), 00214 mSize(0), 00215 mCapacity(capacity > LocalAlloc 00216 ? capacity 00217 : LocalAlloc), 00218 mShareEnum(capacity > LocalAlloc ? Take : Borrow) 00219 { 00220 assert( capacity >= 0 ); 00221 mBuf[mSize] = 0; 00222 } 00223 #endif 00224 00225 Data::Data(const char* str, size_type length) 00226 : mBuf(length > LocalAlloc 00227 ? new char[length + 1] 00228 : mPreBuffer), 00229 mSize(length), 00230 mCapacity(mSize > LocalAlloc 00231 ? mSize 00232 : LocalAlloc), 00233 mShareEnum(mSize > LocalAlloc ? Take : Borrow) 00234 { 00235 if (mSize > 0) 00236 { 00237 assert(str); 00238 memcpy(mBuf, str, mSize); 00239 } 00240 mBuf[mSize]=0; 00241 } 00242 00243 Data::Data(const unsigned char* str, size_type length) 00244 : mBuf(length > LocalAlloc 00245 ? new char[length + 1] 00246 : mPreBuffer), 00247 mSize(length), 00248 mCapacity(mSize > LocalAlloc 00249 ? mSize 00250 : LocalAlloc), 00251 mShareEnum(mSize > LocalAlloc ? Take : Borrow) 00252 { 00253 if (mSize > 0) 00254 { 00255 assert(str); 00256 memcpy(mBuf, str, mSize); 00257 } 00258 mBuf[mSize]=0; 00259 } 00260 00261 // share memory KNOWN to be in a surrounding scope 00262 // wears off on, c_str, operator=, operator+=, non-const 00263 // operator[], append, reserve 00264 Data::Data(const char* str, size_type length, bool) 00265 : mBuf(const_cast<char*>(str)), 00266 mSize(length), 00267 mCapacity(mSize), 00268 mShareEnum(Share) 00269 { 00270 assert(str); 00271 } 00272 00273 Data::Data(ShareEnum se, const char* buffer, size_type length) 00274 : mBuf(const_cast<char*>(buffer)), 00275 mSize(length), 00276 mCapacity(mSize), 00277 mShareEnum(se) 00278 { 00279 assert(buffer); 00280 } 00281 00282 Data::Data(ShareEnum se, const char* buffer) 00283 : mBuf(const_cast<char*>(buffer)), 00284 mSize(strlen(buffer)), 00285 mCapacity(mSize), 00286 mShareEnum(se) 00287 { 00288 assert(buffer); 00289 } 00290 00291 Data::Data(ShareEnum se, const Data& staticData) 00292 : mBuf(staticData.mBuf), 00293 mSize(staticData.mSize), 00294 mCapacity(mSize), 00295 mShareEnum(Share) 00296 { 00297 // !dlb! maybe: 00298 // if you are trying to use Take, but make sure that you unset the mShareEnum on 00299 // the staticData 00300 assert(se == Share); // makes no sense to call this with 'Take'. 00301 } 00302 //============================================================================= 00303 00304 Data::Data(const char* str) // We need mSize to init mBuf; do in body 00305 : mSize(str ? strlen(str) : 0), 00306 mCapacity(mSize > LocalAlloc 00307 ? mSize 00308 : LocalAlloc), 00309 mShareEnum(mSize > LocalAlloc ? Take : Borrow) 00310 { 00311 if(mSize > LocalAlloc) 00312 { 00313 mBuf = new char[mSize+1]; 00314 } 00315 else 00316 { 00317 mBuf = mPreBuffer; 00318 } 00319 00320 if (str) 00321 { 00322 memcpy(mBuf, str, mSize+1); 00323 } 00324 else 00325 { 00326 mBuf[mSize] = 0; 00327 } 00328 } 00329 00330 Data::Data(const string& str) 00331 : mBuf(str.size() > LocalAlloc 00332 ? new char[str.size() + 1] 00333 : mPreBuffer), 00334 mSize(str.size()), 00335 mCapacity(mSize > LocalAlloc 00336 ? mSize 00337 : LocalAlloc), 00338 mShareEnum(mSize > LocalAlloc ? Take : Borrow) 00339 { 00340 memcpy(mBuf, str.c_str(), mSize + 1); 00341 } 00342 00343 Data::Data(const Data& data) 00344 : mBuf(data.mSize > LocalAlloc 00345 ? new char[data.mSize + 1] 00346 : mPreBuffer), 00347 mSize(data.mSize), 00348 mCapacity(mSize > LocalAlloc 00349 ? mSize 00350 : LocalAlloc), 00351 mShareEnum(mSize > LocalAlloc ? Take : Borrow) 00352 { 00353 if (mSize) 00354 { 00355 memcpy(mBuf, data.mBuf, mSize); 00356 } 00357 mBuf[mSize] = 0; 00358 } 00359 00360 #ifdef RESIP_HAS_RVALUE_REFS 00361 Data::Data(Data &&data) 00362 : mBuf(mPreBuffer),mSize(0),mCapacity(LocalAlloc),mShareEnum(Borrow) 00363 { 00364 *this = std::move(data); 00365 } 00366 #endif 00367 00368 // -2147483646 00369 static const int IntMaxSize = 12; 00370 00371 Data::Data(int val) 00372 : mBuf(IntMaxSize > LocalAlloc 00373 ? new char[IntMaxSize + 1] 00374 : mPreBuffer), 00375 mSize(0), 00376 mCapacity(IntMaxSize > LocalAlloc 00377 ? IntMaxSize 00378 : LocalAlloc), 00379 mShareEnum(IntMaxSize > LocalAlloc ? Take : Borrow) 00380 { 00381 if (val == 0) 00382 { 00383 mBuf[0] = '0'; 00384 mBuf[1] = 0; 00385 mSize = 1; 00386 return; 00387 } 00388 00389 bool neg = false; 00390 00391 int value = val; 00392 if (value < 0) 00393 { 00394 value = -value; 00395 neg = true; 00396 } 00397 00398 int c = 0; 00399 int v = value; 00400 while (v /= 10) 00401 { 00402 ++c; 00403 } 00404 00405 if (neg) 00406 { 00407 ++c; 00408 } 00409 00410 mSize = c+1; 00411 mBuf[c+1] = 0; 00412 00413 v = value; 00414 while (v) 00415 { 00416 mBuf[c--] = '0' + v%10; 00417 v /= 10; 00418 } 00419 00420 if (neg) 00421 { 00422 mBuf[0] = '-'; 00423 } 00424 } 00425 00426 static const int MaxLongSize = (sizeof(unsigned long)/sizeof(int))*IntMaxSize; 00427 Data::Data(unsigned long value) 00428 : mBuf(MaxLongSize > LocalAlloc 00429 ? new char[MaxLongSize + 1] 00430 : mPreBuffer), 00431 mSize(0), 00432 mCapacity(MaxLongSize > LocalAlloc 00433 ? MaxLongSize 00434 : LocalAlloc), 00435 mShareEnum(MaxLongSize > LocalAlloc ? Take : Borrow) 00436 { 00437 if (value == 0) 00438 { 00439 mBuf[0] = '0'; 00440 mBuf[1] = 0; 00441 mSize = 1; 00442 return; 00443 } 00444 00445 int c = 0; 00446 unsigned long v = value; 00447 while (v /= 10) 00448 { 00449 ++c; 00450 } 00451 00452 mSize = c+1; 00453 mBuf[c+1] = 0; 00454 00455 v = value; 00456 while (v) 00457 { 00458 unsigned int digit = v%10; 00459 unsigned char d = (char)digit; 00460 mBuf[c--] = '0' + d; 00461 v /= 10; 00462 } 00463 } 00464 00465 #ifndef RESIP_FIXED_POINT 00466 static const int DoubleMaxSize = MaxLongSize + Data::MaxDigitPrecision; 00467 Data::Data(double value, 00468 Data::DoubleDigitPrecision precision) 00469 : mBuf(DoubleMaxSize + precision > LocalAlloc 00470 ? new char[DoubleMaxSize + precision + 1] 00471 : mPreBuffer), 00472 mSize(0), 00473 mCapacity(DoubleMaxSize + precision > LocalAlloc 00474 ? DoubleMaxSize + precision 00475 : LocalAlloc), 00476 mShareEnum(DoubleMaxSize + precision > LocalAlloc ? Take : Borrow) 00477 { 00478 assert(precision >= 0); 00479 assert(precision < MaxDigitPrecision); 00480 00481 double v = value; 00482 bool neg = (value < 0.0); 00483 00484 if (neg) 00485 { 00486 v = -v; 00487 } 00488 00489 Data m((unsigned long)v); 00490 00491 // remainder 00492 v = v - floor(v); 00493 00494 int p = precision; 00495 while (p--) 00496 { 00497 v *= 10; 00498 } 00499 00500 int dec = (int)floor(v+0.5); 00501 Data d(precision, Data::Preallocate); 00502 00503 if (dec == 0) 00504 { 00505 d = "0"; 00506 } 00507 else 00508 { 00509 d.mBuf[precision] = 0; 00510 p = precision; 00511 // neglect trailing zeros 00512 bool significant = false; 00513 while (p--) 00514 { 00515 if (dec % 10 || significant) 00516 { 00517 significant = true; 00518 ++d.mSize; 00519 d.mBuf[p] = '0' + (dec % 10); 00520 } 00521 else 00522 { 00523 d.mBuf[p] = 0; 00524 } 00525 00526 dec /= 10; 00527 } 00528 } 00529 00530 if (neg) 00531 { 00532 mBuf[0] = '-'; 00533 memcpy(mBuf+1, m.mBuf, m.size()); 00534 mBuf[1+m.size()] = '.'; 00535 memcpy(mBuf+1+m.size()+1, d.mBuf, d.size()+1); 00536 mSize = m.size() + d.size() + 2; 00537 } 00538 else 00539 { 00540 if (mCapacity < m.size() + d.size() + 1) 00541 { 00542 resize(m.size() + d.size() + 1, false); 00543 } 00544 memcpy(mBuf, m.mBuf, m.size()); 00545 mBuf[m.size()] = '.'; 00546 memcpy(mBuf+m.size()+1, d.mBuf, d.size()+1); 00547 mSize = m.size() + d.size() + 1; 00548 } 00549 00550 assert(mBuf[mSize] == 0); 00551 } 00552 #endif 00553 00554 Data::Data(unsigned int value) 00555 : mBuf(IntMaxSize > LocalAlloc 00556 ? new char[IntMaxSize + 1] 00557 : mPreBuffer), 00558 mSize(0), 00559 mCapacity(IntMaxSize > LocalAlloc 00560 ? IntMaxSize 00561 : LocalAlloc), 00562 mShareEnum(IntMaxSize > LocalAlloc ? Take : Borrow) 00563 { 00564 if (value == 0) 00565 { 00566 mBuf[0] = '0'; 00567 mBuf[1] = 0; 00568 mSize = 1; 00569 return; 00570 } 00571 00572 int c = 0; 00573 unsigned long v = value; 00574 while (v /= 10) 00575 { 00576 ++c; 00577 } 00578 00579 mSize = c+1; 00580 mBuf[c+1] = 0; 00581 00582 v = value; 00583 while (v) 00584 { 00585 unsigned int digit = v%10; 00586 unsigned char d = (char)digit; 00587 mBuf[c--] = '0' + d; 00588 v /= 10; 00589 } 00590 } 00591 00592 // 18446744073709551615 00593 static const int UInt64MaxSize = 20; 00594 00595 Data::Data(UInt64 value) 00596 : mBuf(UInt64MaxSize > LocalAlloc 00597 ? new char[UInt64MaxSize + 1] 00598 : mPreBuffer), 00599 mSize(0), 00600 mCapacity(UInt64MaxSize > LocalAlloc 00601 ? UInt64MaxSize 00602 : LocalAlloc), 00603 mShareEnum(UInt64MaxSize > LocalAlloc ? Take : Borrow) 00604 { 00605 if (value == 0) 00606 { 00607 mBuf[0] = '0'; 00608 mBuf[1] = 0; 00609 mSize = 1; 00610 return; 00611 } 00612 00613 int c = 0; 00614 UInt64 v = value; 00615 while (v /= 10) 00616 { 00617 ++c; 00618 } 00619 00620 mSize = c+1; 00621 mBuf[c+1] = 0; 00622 00623 v = value; 00624 while (v) 00625 { 00626 UInt64 digit = v%10; 00627 unsigned char d = (char)digit; 00628 mBuf[c--] = '0' + d; 00629 v /= 10; 00630 } 00631 } 00632 00633 static const int CharMaxSize = 1; 00634 Data::Data(char c) 00635 : mBuf(CharMaxSize > LocalAlloc 00636 ? new char[CharMaxSize + 1] 00637 : mPreBuffer), 00638 mSize(1), 00639 mCapacity(CharMaxSize > LocalAlloc 00640 ? CharMaxSize 00641 : LocalAlloc), 00642 mShareEnum(CharMaxSize > LocalAlloc ? Take : Borrow) 00643 { 00644 mBuf[0] = c; 00645 mBuf[1] = 0; 00646 } 00647 00648 Data::Data(bool value) 00649 : mBuf(value ? const_cast<char*>("true") : const_cast<char*>("false")), 00650 mSize(value ? 4 : 5), 00651 mCapacity(value ? 4 : 5), 00652 mShareEnum(Borrow) 00653 {} 00654 00655 Data& 00656 Data::setBuf(ShareEnum se, const char* buffer, size_type length) 00657 { 00658 assert(buffer); 00659 if (mShareEnum == Take) 00660 { 00661 delete[] mBuf; 00662 } 00663 mBuf = const_cast<char*>(buffer); 00664 mCapacity = mSize = length; 00665 mShareEnum = se; 00666 return *this; 00667 } 00668 00669 Data& 00670 Data::takeBuf(Data& other) 00671 { 00672 if ( &other == this ) 00673 return *this; 00674 00675 if (mShareEnum == Data::Take) 00676 delete[] mBuf; 00677 00678 if ( other.mBuf == other.mPreBuffer ) 00679 { 00680 // plus one picks up the terminating safety NULL 00681 memcpy( mPreBuffer, other.mPreBuffer, other.mSize+1); 00682 mBuf = mPreBuffer; 00683 } 00684 else 00685 { 00686 mBuf = other.mBuf; 00687 other.mBuf = other.mPreBuffer; 00688 } 00689 mSize = other.mSize; 00690 mCapacity = other.mCapacity; 00691 mShareEnum = other.mShareEnum; 00692 00693 // reset {other} to same state as the default Data() constructor 00694 // note that other.mBuf is set above 00695 other.mSize = 0; 00696 other.mCapacity = LocalAlloc; 00697 other.mShareEnum = Data::Borrow; 00698 other.mPreBuffer[0] = 0; 00699 00700 return *this; 00701 } 00702 00703 Data& 00704 Data::copy(const char *buf, size_type length) 00705 { 00706 if (mShareEnum == Data::Share || mCapacity < length+1) 00707 { 00708 // will alloc length+1, so the term NULL below is safe 00709 resize(length, false); 00710 } 00711 // {buf} might be part of ourselves already, in which case {length} 00712 // is smaller than our capacity, so resize above won't happen, so 00713 // just memmove (not memcpy) and everything good 00714 mSize = length; 00715 if (mSize>0) 00716 { 00717 memmove(mBuf, buf, mSize); 00718 } 00719 // DONT do term NULL until after copy, because may be shifting contents 00720 // down and don't want to put NULL in middle of it 00721 mBuf[mSize] = 0; 00722 return *this; 00723 } 00724 00725 char* 00726 Data::getBuf(size_type length) 00727 { 00728 if (mShareEnum == Data::Share || mCapacity < length) 00729 { 00730 // will alloc length+1, so the term NULL below is safe 00731 resize(length, false); 00732 mBuf[length] = 0; 00733 } 00734 else if ( mCapacity != length ) 00735 { 00736 mBuf[length] = 0; 00737 } 00738 // even if we don't NULL-term it, it may have NULL term from before. 00739 // But if external buffer (taken or borrow'd) then don't know if it 00740 // has a NULL or not. 00741 mSize = length; 00742 return mBuf; 00743 } 00744 00745 bool 00746 resip::operator==(const Data& lhs, const Data& rhs) 00747 { 00748 if (lhs.mSize != rhs.mSize) 00749 { 00750 return false; 00751 } 00752 return memcmp(lhs.mBuf, rhs.mBuf, lhs.mSize) == 0; 00753 } 00754 00755 bool 00756 resip::operator==(const Data& lhs, const char* rhs) 00757 { 00758 assert(rhs); // .dlb. not consistent with constructor 00759 if (memcmp(lhs.mBuf, rhs, lhs.mSize) != 0) 00760 { 00761 return false; 00762 } 00763 else 00764 { 00765 // make sure the string terminates at size 00766 return (rhs[lhs.mSize] == 0); 00767 } 00768 } 00769 00770 bool 00771 resip::operator<(const Data& lhs, const Data& rhs) 00772 { 00773 int res = memcmp(lhs.mBuf, rhs.mBuf, resipMin(lhs.mSize, rhs.mSize)); 00774 00775 if (res < 0) 00776 { 00777 return true; 00778 } 00779 else if (res > 0) 00780 { 00781 return false; 00782 } 00783 else 00784 { 00785 return (lhs.mSize < rhs.mSize); 00786 } 00787 } 00788 00789 bool 00790 resip::operator<(const Data& lhs, const char* rhs) 00791 { 00792 assert(rhs); 00793 Data::size_type l = strlen(rhs); 00794 int res = memcmp(lhs.mBuf, rhs, resipMin(lhs.mSize, l)); 00795 00796 if (res < 0) 00797 { 00798 return true; 00799 } 00800 else if (res > 0) 00801 { 00802 return false; 00803 } 00804 else 00805 { 00806 return (lhs.mSize < l); 00807 } 00808 } 00809 00810 bool 00811 resip::operator<(const char* lhs, const Data& rhs) 00812 { 00813 assert(lhs); 00814 Data::size_type l = strlen(lhs); 00815 int res = memcmp(lhs, rhs.mBuf, resipMin(l, rhs.mSize)); 00816 00817 if (res < 0) 00818 { 00819 return true; 00820 } 00821 else if (res > 0) 00822 { 00823 return false; 00824 } 00825 else 00826 { 00827 return (l < rhs.mSize); 00828 } 00829 } 00830 00831 00832 00833 #if 0 00834 // Moved to inline header as special case of copy() 00835 Data& 00836 Data::operator=(const Data& data) 00837 { 00838 assert(mBuf); 00839 00840 if (&data != this) 00841 { 00842 if (mShareEnum == Share) 00843 { 00844 resize(data.mSize, false); 00845 } 00846 else 00847 { 00848 if (data.mSize > mCapacity) 00849 { 00850 resize(data.mSize, false); 00851 } 00852 } 00853 00854 mSize = data.mSize; 00855 // could overlap! 00856 if (mSize > 0) 00857 { 00858 memmove(mBuf, data.mBuf, mSize); 00859 } 00860 mBuf[mSize] = 0; 00861 } 00862 return *this; 00863 } 00864 #endif 00865 00866 #ifdef RESIP_HAS_RVALUE_REFS 00867 Data& Data::operator=(Data &&data) 00868 { 00869 if (&data != this) 00870 { 00871 if (data.mPreBuffer != data.mBuf) 00872 { 00873 //data is not using the local buffer, take ownership of data. 00874 mBuf = data.mBuf; 00875 mCapacity = data.mCapacity; 00876 mShareEnum = data.mShareEnum; 00877 mSize = data.mSize; 00878 data.mShareEnum = Borrow; //don't delete the transferred buffer in data's destructor. 00879 } 00880 else 00881 { 00882 *this = data; //lvalue assignment operator will be called for named rvalue. 00883 } 00884 } 00885 00886 return *this; 00887 } 00888 #endif 00889 00890 Data::size_type 00891 Data::truncate(size_type len) 00892 { 00893 if (len < mSize) 00894 { 00895 (*this)[len] = 0; 00896 mSize = len; 00897 } 00898 00899 return mSize; 00900 } 00901 00902 Data& 00903 Data::truncate2(size_type len) 00904 { 00905 if (len < mSize) 00906 { 00907 // NOTE: Do not write terminating NULL, to avoid un-doing Share 00908 mSize = len; 00909 } 00910 return *this; 00911 } 00912 00913 Data 00914 Data::operator+(const Data& data) const 00915 { 00916 Data tmp(mSize + (int)data.mSize, Data::Preallocate); 00917 tmp.mSize = mSize + data.mSize; 00918 tmp.mCapacity = tmp.mSize; 00919 memcpy(tmp.mBuf, mBuf, mSize); 00920 memcpy(tmp.mBuf + mSize, data.mBuf, data.mSize); 00921 tmp.mBuf[tmp.mSize] = 0; 00922 00923 return tmp; 00924 } 00925 00926 Data& 00927 Data::operator^=(const Data& rhs) 00928 { 00929 if (mCapacity < rhs.mSize) 00930 { 00931 resize(rhs.mSize, true); 00932 } 00933 if (mSize < rhs.mSize) 00934 { 00935 memset(mBuf+mSize, 0, mCapacity - mSize); 00936 } 00937 00938 char* c1 = mBuf; 00939 char* c2 = rhs.mBuf; 00940 char* end = c2 + rhs.mSize; 00941 while (c2 != end) 00942 { 00943 *c1++ ^= *c2++; 00944 } 00945 mSize = resipMax(mSize, rhs.mSize); 00946 00947 return *this; 00948 } 00949 00950 char& 00951 Data::at(size_type p) 00952 { 00953 if (p >= mCapacity) 00954 { 00955 resize(p+1, true); 00956 } 00957 else 00958 { 00959 own(); 00960 if (p > mSize) 00961 { 00962 mSize = p + 1; 00963 mBuf[mSize] = 0; 00964 } 00965 } 00966 return mBuf[p]; 00967 } 00968 00969 #if 0 00970 // Moved to inline header as special case of copy() 00971 Data& 00972 Data::operator=(const char* str) 00973 { 00974 assert(str); 00975 size_type l = strlen(str); 00976 00977 if (mShareEnum == Share) 00978 { 00979 resize(l, false); 00980 } 00981 else 00982 { 00983 if (l > mCapacity) 00984 { 00985 resize(l, false); 00986 } 00987 } 00988 00989 mSize = l; 00990 // could conceivably overlap 00991 memmove(mBuf, str, mSize+1); 00992 00993 return *this; 00994 } 00995 #endif 00996 00997 Data 00998 Data::operator+(const char* str) const 00999 { 01000 assert(str); 01001 size_t l = strlen(str); 01002 Data tmp(mSize + l, Data::Preallocate); 01003 tmp.mSize = mSize + l; 01004 tmp.mCapacity = tmp.mSize; 01005 memcpy(tmp.mBuf, mBuf, mSize); 01006 memcpy(tmp.mBuf + mSize, str, l+1); 01007 01008 return tmp; 01009 } 01010 01011 void 01012 Data::reserve(size_type len) 01013 { 01014 if (len > mCapacity) 01015 { 01016 resize(len, true); 01017 } 01018 } 01019 01020 Data& 01021 Data::append(const char* str, size_type len) 01022 { 01023 assert(str); 01024 if (mCapacity <= mSize + len) // append null terminates, thus the equality 01025 { 01026 // .dlb. pad for future growth? 01027 resize(((mSize + len +16)*3)/2, true); 01028 } 01029 else 01030 { 01031 if (mShareEnum == Share) 01032 { 01033 resize(mSize + len, true); 01034 } 01035 } 01036 01037 // could conceivably overlap 01038 memmove(mBuf + mSize, str, len); 01039 mSize += len; 01040 mBuf[mSize] = 0; 01041 01042 return *this; 01043 } 01044 01045 01046 Data 01047 Data::operator+(char c) const 01048 { 01049 Data tmp(mSize + 1, Data::Preallocate); 01050 tmp.mSize = mSize + 1; 01051 tmp.mCapacity = tmp.mSize; 01052 memcpy(tmp.mBuf, mBuf, mSize); 01053 tmp.mBuf[mSize] = c; 01054 tmp.mBuf[mSize+1] = 0; 01055 01056 return tmp; 01057 } 01058 01059 const char* 01060 Data::c_str() const 01061 { 01062 if (mShareEnum == Data::Share || mSize == mCapacity) 01063 { 01064 const_cast<Data*>(this)->resize(mSize+1,true); 01065 } 01066 // mostly is zero terminated, but not by DataStream 01067 mBuf[mSize] = 0; 01068 return mBuf; 01069 } 01070 01071 void 01072 Data::own() const 01073 { 01074 if (mShareEnum == Share) 01075 { 01076 const_cast<Data*>(this)->resize(mSize, true); 01077 } 01078 } 01079 01080 // generate additional capacity 01081 void 01082 Data::resize(size_type newCapacity, 01083 bool copy) 01084 { 01085 assert(newCapacity >= mCapacity || mShareEnum == Data::Share); 01086 01087 char *oldBuf = mBuf; 01088 bool needToDelete=(mShareEnum==Take); 01089 01090 if(newCapacity > LocalAlloc) 01091 { 01092 mBuf = new char[newCapacity+1]; 01093 mShareEnum = Take; 01094 } 01095 else 01096 { 01097 mBuf = mPreBuffer; 01098 mShareEnum = Borrow; 01099 } 01100 01101 if (copy) 01102 { 01103 memcpy(mBuf, oldBuf, mSize); 01104 mBuf[mSize] = 0; 01105 } 01106 01107 if (needToDelete) 01108 { 01109 delete[] oldBuf; 01110 } 01111 01112 mCapacity = newCapacity; 01113 } 01114 01115 Data 01116 Data::md5(EncodingType type) const 01117 { 01118 MD5Context context; 01119 MD5Init(&context); 01120 MD5Update(&context, reinterpret_cast < unsigned const char* > (mBuf), (unsigned int)mSize); 01121 01122 unsigned char digestBuf[16]; 01123 MD5Final(digestBuf, &context); 01124 Data digest(digestBuf,16); 01125 01126 switch(type) 01127 { 01128 case BINARY: 01129 return digest; 01130 case BASE64: 01131 return digest.base64encode(true); 01132 case HEX: 01133 default: 01134 return digest.hex(); 01135 } 01136 assert(0); 01137 return digest.hex(); 01138 } 01139 01140 Data 01141 Data::escaped() const 01142 { 01143 Data ret((int)((size()*11)/10), Data::Preallocate); 01144 01145 const char* p = data(); 01146 for (size_type i=0; i < size(); ++i) 01147 { 01148 unsigned char c = *p++; 01149 01150 if ( c == 0x0d ) 01151 { 01152 if ( i+1 < size() ) 01153 { 01154 if ( *p == 0x0a ) 01155 { 01156 // found a CRLF sequence 01157 ret += c; 01158 c = *p++; i++; 01159 ret += c; 01160 continue; 01161 } 01162 } 01163 } 01164 01165 if ( !isprint(c) ) 01166 { 01167 ret +='%'; 01168 01169 int hi = (c & 0xF0)>>4; 01170 int low = (c & 0x0F); 01171 01172 ret += hexmap[hi]; 01173 ret += hexmap[low]; 01174 } 01175 else 01176 { 01177 ret += c; 01178 } 01179 } 01180 01181 return ret; 01182 } 01183 01184 Data 01185 Data::charEncoded() const 01186 { 01187 Data ret((int)((size()*11)/10), Data::Preallocate); 01188 01189 const char* p = data(); 01190 for (size_type i=0; i < size(); ++i) 01191 { 01192 unsigned char c = *p++; 01193 01194 if ( c == 0x0d ) 01195 { 01196 if ( i+1 < size() ) 01197 { 01198 if ( *p == 0x0a ) 01199 { 01200 // found a CRLF sequence 01201 ret += c; 01202 c = *p++; i++; 01203 ret += c; 01204 continue; 01205 } 01206 } 01207 } 01208 01209 if ( !isprint(c) || 01210 // rfc 3261 reserved + mark + space + tab 01211 strchr(" \";/?:@&=+%$,\t-_.!~*'()", c)) 01212 { 01213 ret +='%'; 01214 01215 int hi = (c & 0xF0)>>4; 01216 int low = (c & 0x0F); 01217 01218 ret += hexmap[hi]; 01219 ret += hexmap[low]; 01220 } 01221 else 01222 { 01223 ret += c; 01224 } 01225 } 01226 01227 return ret; 01228 } 01229 01230 Data 01231 Data::charUnencoded() const 01232 { 01233 Data ret(size(), Data::Preallocate); 01234 01235 const char* p = data(); 01236 for (size_type i = 0; i < size(); ++i) 01237 { 01238 unsigned char c = *p++; 01239 if (c == '%') 01240 { 01241 if ( i+2 < size()) 01242 { 01243 const char* high = strchr(hexmap, tolower(*p++)); 01244 const char* low = strchr(hexmap, tolower(*p++)); 01245 01246 // !rwm! changed from high==0 || low==0 01247 if (high == 0 && low == 0) 01248 { 01249 assert(0); 01250 // ugh 01251 return ret; 01252 } 01253 01254 int highInt = int(high - hexmap); 01255 int lowInt = int(low - hexmap); 01256 ret += char(highInt<<4 | lowInt); 01257 i += 2; 01258 } 01259 else 01260 { 01261 break; 01262 } 01263 } 01264 else 01265 { 01266 ret += c; 01267 } 01268 } 01269 return ret; 01270 } 01271 01272 Data 01273 Data::urlEncoded() const 01274 { 01275 Data buffer; 01276 DataStream strm(buffer); 01277 urlEncode(strm); 01278 strm.flush(); 01279 return buffer; 01280 } 01281 01282 Data 01283 Data::urlDecoded() const 01284 { 01285 Data buffer; 01286 DataStream strm(buffer); 01287 urlDecode(strm); 01288 strm.flush(); 01289 return buffer; 01290 } 01291 01292 EncodeStream& 01293 Data::urlDecode(EncodeStream& s) const 01294 { 01295 unsigned int i = 0; 01296 for (const char* p = data(); p != data()+size(); ++p, ++i) 01297 { 01298 unsigned char c = *p; 01299 if (c == '%') 01300 { 01301 if (i+2 < size()) 01302 { 01303 s << (char) hexpair2int( *(p+1), *(p+2)); 01304 p += 2; 01305 } 01306 else 01307 { 01308 break; 01309 } 01310 } 01311 else if (c == '+') 01312 { 01313 s << ' '; 01314 } 01315 else 01316 { 01317 s << c; 01318 } 01319 } 01320 return s; 01321 } 01322 01323 bool urlNonEncodedChars[256] = {false}; 01324 bool 01325 urlNonEncodedCharsInitFn() 01326 { 01327 // query part of HTTP URL can be a pchar, slash, or question 01328 // pchar is unreserved, subdelims, colon, at-sign 01329 01330 for (int i = 0; i < 256; ++i) 01331 { 01332 unsigned char c(i); 01333 urlNonEncodedChars[c] = (isalpha(c) || // unreserved 01334 isdigit(c) || // unreserved 01335 c == '-' || // these first 4 are unreserved 01336 c == '_' || 01337 c == '.' || 01338 c == '~' || 01339 c == '!' || // these are subdelims (allowed in pchars) 01340 c == '$' || 01341 // c == '&' || // while these are allowed subdelims, this is an error 01342 // c == '+' || // I believe this is an error as well. 01343 c == '\'' || 01344 c == '(' || 01345 c == ')' || 01346 c == '*' || 01347 c == ',' || 01348 c == ';' || 01349 c == '=' || 01350 c == ':' || // next two explicitly allowed in pchar 01351 c == '@' || 01352 c == '/' || // next two explicitly allowed in query in addition to pchar 01353 c == '?'); 01354 } 01355 01356 return false; 01357 } 01358 01359 static bool dummy = urlNonEncodedCharsInitFn(); 01360 01361 // e.g. http://www.blooberry.com/indexdot/html/topics/urlencoding.htm 01362 EncodeStream& 01363 Data::urlEncode(EncodeStream& s) const 01364 { 01365 for (const char* p = data(); p != data() + size(); ++p) 01366 { 01367 unsigned char c = *p; 01368 01369 // pchar, slash, questionmark 01370 // pchar = unreserved, sub-delims, colon, at-sign 01371 // unreserved = alphanum, hyphen, underscore, period, tilde 01372 // subdelims = bang (!), dollar, ampersand (oops!), plus, single-quote, lparen, rparen, asterisk, comma, semicolon, equal 01373 //if (isalpha(c) || isdigit(c) || strchr("-_.~!$+'()*,;=:@/?", c)) // 01374 // strchr is inefficient and wrong 01375 if (urlNonEncodedChars[c]) 01376 { 01377 s << c; 01378 } 01379 else 01380 { 01381 if (c == 0x20) 01382 { 01383 s << '+'; 01384 } 01385 else 01386 { 01387 s << '%' << (hexmap[(c & 0xF0)>>4]) << (hexmap[(c & 0x0F)]); 01388 } 01389 } 01390 } 01391 01392 return s; 01393 } 01394 01395 Data 01396 Data::xmlCharDataEncode() const 01397 { 01398 Data buffer; 01399 DataStream strm(buffer); 01400 xmlCharDataEncode(strm); 01401 strm.flush(); 01402 return buffer; 01403 } 01404 01405 Data 01406 Data::xmlCharDataDecode() const 01407 { 01408 Data buffer; 01409 DataStream strm(buffer); 01410 xmlCharDataDecode(strm); 01411 strm.flush(); 01412 return buffer; 01413 } 01414 01415 // http://www.w3.org/TR/REC-xml/#syntax 01416 EncodeStream& 01417 Data::xmlCharDataEncode(EncodeStream& s) const 01418 { 01419 for (const char* p = data(); p != data() + size(); ++p) 01420 { 01421 unsigned char c = *p; 01422 01423 switch(c) 01424 { 01425 case '&': 01426 s << "&"; 01427 break; 01428 case '<': 01429 s << "<"; 01430 break; 01431 case '>': 01432 s << ">"; 01433 break; 01434 case '\'': 01435 s << "'"; 01436 break; 01437 case '\"': 01438 s << """; 01439 break; 01440 default: 01441 s << c; 01442 } 01443 } 01444 01445 return s; 01446 } 01447 01448 EncodeStream& 01449 Data::xmlCharDataDecode(EncodeStream& s) const 01450 { 01451 unsigned int i = 0; 01452 for (const char* p = data(); p != data()+size(); ++p, ++i) 01453 { 01454 unsigned char c = *p; 01455 if (c == '&') 01456 { 01457 // look for amp; 01458 if(i+4 < size() && 01459 *(p+1) == 'a' && *(p+2) == 'm' && *(p+3) == 'p' && *(p+4) == ';') 01460 { 01461 s << '&'; 01462 p += 4; 01463 } 01464 // look for lt; 01465 else if(i+3 < size() && 01466 *(p+1) == 'l' && *(p+2) == 't' && *(p+3) == ';') 01467 { 01468 s << '<'; 01469 p += 3; 01470 } 01471 // look for gt; 01472 else if(i+3 < size() && 01473 *(p+1) == 'g' && *(p+2) == 't' && *(p+3) == ';') 01474 { 01475 s << '>'; 01476 p += 3; 01477 } 01478 // look for apos; 01479 else if(i+5 < size() && 01480 *(p+1) == 'a' && *(p+2) == 'p' && *(p+3) == 'o' && *(p+4) == 's' && *(p+5) == ';') 01481 { 01482 s << '\''; 01483 p += 5; 01484 } 01485 // look for quot; 01486 else if(i+5 < size() && 01487 *(p+1) == 'q' && *(p+2) == 'u' && *(p+3) == 'o' && *(p+4) == 't' && *(p+5) == ';') 01488 { 01489 s << '\"'; 01490 p += 5; 01491 } 01492 else // if no conversion found - just leave characters in data 01493 { 01494 s << c; 01495 } 01496 } 01497 else 01498 { 01499 s << c; 01500 } 01501 } 01502 return s; 01503 } 01504 01505 Data 01506 Data::trunc(size_type s) const 01507 { 01508 if (size() <= s) 01509 { 01510 return *this; 01511 } 01512 else 01513 { 01514 return Data(data(), s) + ".."; 01515 } 01516 } 01517 01518 Data 01519 Data::hex() const 01520 { 01521 Data ret( 2*mSize, Data::Preallocate); 01522 01523 const char* p = mBuf; 01524 char* r = ret.mBuf; 01525 for (size_type i=0; i < mSize; ++i) 01526 { 01527 unsigned char temp = *p++; 01528 01529 int hi = (temp & 0xf0)>>4; 01530 int low = (temp & 0xf); 01531 01532 *r++ = hexmap[hi]; 01533 *r++ = hexmap[low]; 01534 } 01535 *r = 0; 01536 ret.mSize = 2*mSize; 01537 return ret; 01538 } 01539 01540 Data& 01541 Data::lowercase() 01542 { 01543 own(); 01544 char* p = mBuf; 01545 for (size_type i=0; i < mSize; ++i) 01546 { 01547 *p = tolower(*p); 01548 ++p; 01549 } 01550 return *this; 01551 } 01552 01553 Data& 01554 Data::uppercase() 01555 { 01556 own(); 01557 char* p = mBuf; 01558 for (size_type i=0; i < mSize; ++i) 01559 { 01560 *p = toupper(*p); 01561 ++p; 01562 } 01563 return *this; 01564 } 01565 01566 Data& 01567 Data::schemeLowercase() 01568 { 01569 own(); 01570 char* p = mBuf; 01571 for (size_type i=0; i < mSize; ++i) 01572 { 01573 *p |= ' '; 01574 ++p; 01575 } 01576 return *this; 01577 } 01578 01579 #if 0 01580 // in-lined into header as special case of truncate2() 01581 Data& 01582 Data::clear() 01583 { 01584 mSize = 0; 01585 return *this; 01586 } 01587 #endif 01588 01589 int 01590 Data::convertInt() const 01591 { 01592 int val = 0; 01593 char* p = mBuf; 01594 const char* const end = mBuf + mSize; 01595 int s = 1; 01596 01597 for (; p != end; ++p) 01598 { 01599 if (!isspace(*p)) 01600 { 01601 goto sign_char; 01602 } 01603 } 01604 return val; 01605 sign_char: 01606 01607 if (*p == '-') 01608 { 01609 s = -1; 01610 ++p; 01611 } 01612 else if (*p == '+') 01613 { 01614 ++p; 01615 } 01616 01617 for(; p != end; ++p) 01618 { 01619 if (!isdigit(*p)) 01620 { 01621 break; 01622 } 01623 val *= 10; 01624 val += (*p) - '0'; 01625 } 01626 return s*val; 01627 } 01628 01629 unsigned long 01630 Data::convertUnsignedLong() const 01631 { 01632 unsigned long val = 0; 01633 char* p = mBuf; 01634 const char* const end = mBuf + mSize; 01635 01636 for (; p != end; ++p) 01637 { 01638 if (!isspace(*p)) 01639 { 01640 goto sign_char; 01641 } 01642 } 01643 return val; 01644 sign_char: 01645 01646 if (*p == '+') 01647 { 01648 ++p; 01649 } 01650 01651 for(; p != end; ++p) 01652 { 01653 if (!isdigit(*p)) 01654 { 01655 break; 01656 } 01657 val *= 10; 01658 val += (*p) - '0'; 01659 } 01660 return val; 01661 } 01662 01663 UInt64 01664 Data::convertUInt64() const 01665 { 01666 UInt64 val = 0; 01667 char* p = mBuf; 01668 const char* const end = mBuf + mSize; 01669 01670 for (; p != end; ++p) 01671 { 01672 if (!isspace(*p)) 01673 { 01674 goto sign_char; 01675 } 01676 } 01677 return val; 01678 sign_char: 01679 01680 if (*p == '+') 01681 { 01682 ++p; 01683 } 01684 01685 for(; p != end; ++p) 01686 { 01687 if (!isdigit(*p)) 01688 { 01689 break; 01690 } 01691 val *= 10; 01692 val += (*p) - '0'; 01693 } 01694 return val; 01695 } 01696 01697 size_t 01698 Data::convertSize() const 01699 { 01700 size_t val = 0; 01701 char* p = mBuf; 01702 const char* const end = mBuf + mSize; 01703 01704 for (; p != end; ++p) 01705 { 01706 if (!isspace(*p)) 01707 { 01708 goto sign_char; 01709 } 01710 } 01711 return val; 01712 sign_char: 01713 01714 if (*p == '+') 01715 { 01716 ++p; 01717 } 01718 01719 for(; p != end; ++p) 01720 { 01721 if (!isdigit(*p)) 01722 { 01723 break; 01724 } 01725 val *= 10; 01726 val += (*p) - '0'; 01727 } 01728 return val; 01729 } 01730 01731 #ifndef RESIP_FIXED_POINT 01732 double 01733 Data::convertDouble() const 01734 { 01735 long val = 0; 01736 char* p = mBuf; 01737 const char* const end = p + mSize; 01738 int s = 1; 01739 01740 for (; p != end; ++p) 01741 { 01742 if (!isspace(*p)) 01743 { 01744 goto sign_char; 01745 } 01746 } 01747 return val; 01748 sign_char: 01749 01750 if (*p == '-') 01751 { 01752 s = -1; 01753 ++p; 01754 } 01755 else if (*p == '+') 01756 { 01757 ++p; 01758 } 01759 01760 for(; p != end; ++p) 01761 { 01762 if (*p == '.') 01763 { 01764 goto decimals; 01765 } 01766 if (!isdigit(*p)) 01767 { 01768 return s*val; 01769 } 01770 val *= 10; 01771 val += (*p) - '0'; 01772 } 01773 return s*val; 01774 01775 decimals: 01776 ++p; 01777 long d = 0; 01778 double div = 1.0; 01779 for(; p != end; ++p) 01780 { 01781 if (!isdigit(*p)) 01782 { 01783 break; 01784 } 01785 d *= 10; 01786 d += *p - '0'; 01787 div *= 10; 01788 } 01789 return s*(val + d/div); 01790 } 01791 #endif 01792 01793 bool 01794 Data::prefix(const Data& pre) const 01795 { 01796 if (pre.size() > size()) 01797 { 01798 return false; 01799 } 01800 01801 return memcmp(data(), pre.data(), pre.size()) == 0; 01802 } 01803 01804 bool 01805 Data::postfix(const Data& post) const 01806 { 01807 if (post.size() > size()) 01808 { 01809 return false; 01810 } 01811 01812 return memcmp(data() + (size()-post.size()), post.data(), post.size()) == 0; 01813 } 01814 01815 Data 01816 Data::substr(size_type first, size_type count) const 01817 { 01818 assert(first <= mSize); 01819 if ( count == Data::npos) 01820 { 01821 return Data(mBuf+first, mSize-first); 01822 } 01823 else 01824 { 01825 assert(first + count <= mSize); 01826 return Data(mBuf+first, count); 01827 } 01828 } 01829 01830 Data::size_type 01831 Data::find(const Data& match, 01832 size_type start) const 01833 { 01834 if (start < mSize) 01835 { 01836 ParseBuffer pb(mBuf + start, mSize - start); 01837 pb.skipToChars(match); 01838 if (!pb.eof()) 01839 { 01840 return pb.position() - pb.start() + start; 01841 } 01842 } 01843 01844 return Data::npos; 01845 } 01846 01847 int 01848 Data::replace(const Data& match, 01849 const Data& replaceWith, 01850 int max) 01851 { 01852 assert(!match.empty()); 01853 01854 int count = 0; 01855 01856 const int incr = int(replaceWith.size() - match.size()); 01857 for (size_type offset = find(match, 0); 01858 count < max && offset != Data::npos; 01859 offset = find(match, offset+replaceWith.size())) 01860 { 01861 if (mSize + incr >= mCapacity) 01862 { 01863 resize((mCapacity + incr) * 3 / 2, true); 01864 } 01865 else 01866 { 01867 own(); 01868 } 01869 01870 // move the memory forward (or backward) 01871 memmove(mBuf + offset + replaceWith.size(), mBuf + offset + match.size(), mSize - offset - match.size()); 01872 memcpy(mBuf + offset, replaceWith.data(), replaceWith.size()); 01873 mSize += incr; 01874 01875 ++count; 01876 } 01877 01878 return count; 01879 } 01880 01881 #ifndef RESIP_USE_STL_STREAMS 01882 EncodeStream& 01883 resip::operator<<(EncodeStream& strm, const Data& d) 01884 { 01885 return strm.write(d.mBuf, d.mSize); 01886 } 01887 #endif 01888 01889 // random permutation of 0..255 01890 static const unsigned char randomPermutation[256] = 01891 { 01892 44, 9, 46, 184, 21, 30, 92, 231, 79, 7, 166, 237, 173, 72, 91, 123, 01893 212, 183, 16, 99, 85, 45, 190, 130, 118, 107, 169, 119, 100, 179, 251, 177, 01894 23, 125, 12, 101, 121, 246, 61, 38, 156, 114, 159, 57, 181, 145, 198, 182, 01895 58, 215, 174, 225, 82, 178, 150, 161, 63, 103, 32, 203, 68, 151, 139, 55, 01896 143, 2, 36, 110, 209, 154, 204, 89, 62, 17, 187, 226, 31, 105, 195, 208, 01897 49, 56, 238, 172, 37, 3, 234, 206, 134, 233, 19, 148, 64, 4, 10, 224, 01898 144, 88, 93, 191, 20, 131, 138, 199, 243, 244, 39, 50, 214, 87, 6, 84, 01899 185, 112, 171, 75, 192, 193, 239, 69, 106, 43, 194, 1, 78, 67, 116, 200, 01900 83, 70, 213, 25, 59, 137, 52, 13, 153, 42, 232, 0, 133, 210, 76, 33, 01901 255, 236, 124, 104, 65, 201, 53, 155, 140, 254, 54, 196, 120, 146, 216, 29, 01902 28, 86, 245, 90, 98, 26, 81, 115, 180, 66, 102, 136, 167, 51, 109, 132, 01903 77, 175, 14, 202, 222, 48, 223, 188, 40, 242, 157, 5, 128, 229, 71, 127, 01904 164, 207, 247, 8, 80, 149, 94, 160, 47, 117, 135, 176, 129, 142, 189, 97, 01905 11, 250, 221, 218, 96, 220, 35, 197, 152, 126, 219, 74, 170, 252, 163, 41, 01906 95, 27, 34, 22, 205, 230, 241, 186, 168, 228, 253, 249, 113, 108, 111, 211, 01907 235, 217, 165, 122, 15, 141, 158, 147, 240, 24, 162, 18, 60, 73, 227, 248 01908 }; 01909 01910 size_t 01911 Data::rawHash(const unsigned char* c, size_t size) 01912 { 01913 // 4 byte Pearson's hash 01914 // essentially random hashing 01915 01916 union 01917 { 01918 size_t st; 01919 unsigned char bytes[4]; 01920 }; 01921 st = 0; // suppresses warnings about unused st 01922 bytes[0] = randomPermutation[0]; 01923 bytes[1] = randomPermutation[1]; 01924 bytes[2] = randomPermutation[2]; 01925 bytes[3] = randomPermutation[3]; 01926 01927 const unsigned char* end = c + size; 01928 for ( ; c != end; ++c) 01929 { 01930 bytes[0] = randomPermutation[*c ^ bytes[0]]; 01931 bytes[1] = randomPermutation[*c ^ bytes[1]]; 01932 bytes[2] = randomPermutation[*c ^ bytes[2]]; 01933 bytes[3] = randomPermutation[*c ^ bytes[3]]; 01934 } 01935 01936 // convert from network to host byte order 01937 return ntohl((u_long)st); 01938 } 01939 01940 // use only for ascii characters! 01941 size_t 01942 Data::rawCaseInsensitiveHash(const unsigned char* c, size_t size) 01943 { 01944 01945 union 01946 { 01947 size_t st; 01948 unsigned char bytes[4]; 01949 }; 01950 st = 0; // suppresses warnings about unused st 01951 bytes[0] = randomPermutation[0]; 01952 bytes[1] = randomPermutation[1]; 01953 bytes[2] = randomPermutation[2]; 01954 bytes[3] = randomPermutation[3]; 01955 01956 const unsigned char* end = c + size; 01957 for ( ; c != end; ++c) 01958 { 01959 unsigned char cc = tolower(*c); 01960 bytes[0] = randomPermutation[cc ^ bytes[0]]; 01961 bytes[1] = randomPermutation[cc ^ bytes[1]]; 01962 bytes[2] = randomPermutation[cc ^ bytes[2]]; 01963 bytes[3] = randomPermutation[cc ^ bytes[3]]; 01964 } 01965 01966 // convert from network to host byte order 01967 return ntohl((u_long)st); 01968 } 01969 01970 #undef get16bits 01971 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ 01972 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) 01973 #define get16bits(d) (*((const UInt16 *) (d))) 01974 #endif 01975 01976 #if !defined (get16bits) 01977 #define get16bits(d) ((((UInt32)(((const UInt8 *)(d))[1])) << 8)\ 01978 +(UInt32)(((const UInt8 *)(d))[0]) ) 01979 #endif 01980 01981 #undef get32bits 01982 #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ 01983 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) 01984 #define get32bits(d) (*((const UInt32 *) (d))) 01985 #endif 01986 01987 #if !defined (get32bits) 01988 #define get32bits(d) ((get16bits(d+2) << 16) + get16bits(d)) 01989 #endif 01990 01991 // This is intended to be a faster case-insensitive hash function that works 01992 // well when the buffer is a RFC 3261 token. 01993 // Having non-token characters will not prevent the hash from working, but it 01994 // will increase the number of cases where a single char difference will result 01995 // in a hash collision. The pairs of _printable_ characters that this hash will 01996 // not distinguish between are @`, [{, \|, ]} and ^~ 01997 // (Note that, for RFC 3261 tokens, this will not be a problem since @, [, {, \, 01998 // |, ], } and ^ are not allowed in a token.) 01999 size_t 02000 Data::rawCaseInsensitiveTokenHash(const unsigned char* data, size_t len) 02001 { 02002 // .bwc. Hsieh hash, with some bitmasking to get the case-insensitive 02003 // property (this is what all the "0x2020 |" business is about.) 02004 UInt32 hash = len, tmp; 02005 int rem; 02006 02007 if (len <= 0 || data == NULL) return 0; 02008 02009 rem = len & 3; 02010 len >>= 2; 02011 02012 union 02013 { 02014 UInt32 masked; 02015 UInt16 ui16[2]; 02016 }; 02017 02018 /* Main loop */ 02019 for (;len > 0; len--) 02020 { 02021 // mask out bit 6 for case-insensitivity 02022 masked = (0x20202020 | get32bits(data)); 02023 hash += ui16[0]; 02024 tmp = ((UInt32)ui16[1] << 11) ^ hash; 02025 hash = (hash << 16) ^ tmp; 02026 data += 2*sizeof (UInt16); 02027 hash += hash >> 11; 02028 } 02029 02030 /* Handle end cases */ 02031 switch (rem) 02032 { 02033 case 3: hash += (0x2020 | get16bits (data)); 02034 hash ^= hash << 16; 02035 hash ^= (0x20 | data[sizeof (UInt16)]) << 18; 02036 hash += hash >> 11; 02037 break; 02038 case 2: hash += (0x2020 | get16bits (data)); 02039 hash ^= hash << 11; 02040 hash += hash >> 17; 02041 break; 02042 case 1: hash += (0x20 | *data); 02043 hash ^= hash << 10; 02044 hash += hash >> 1; 02045 } 02046 02047 /* Force "avalanching" of final 127 bits */ 02048 hash ^= hash << 3; 02049 hash += hash >> 5; 02050 hash ^= hash << 4; 02051 hash += hash >> 17; 02052 hash ^= hash << 25; 02053 hash += hash >> 6; 02054 02055 return hash; 02056 02057 // union 02058 // { 02059 // size_t st; 02060 // unsigned char bytes[4]; 02061 // }; 02062 // st = 0; // suppresses warnings about unused st 02063 // bytes[0] = randomPermutation[0]; 02064 // bytes[1] = randomPermutation[1]; 02065 // bytes[2] = randomPermutation[2]; 02066 // bytes[3] = randomPermutation[3]; 02067 // 02068 // const unsigned char* end = c + size; 02069 // for ( ; c != end; ++c) 02070 // { 02071 // union 02072 // { 02073 // UInt32 temp; 02074 // UInt8 cccc[4]; 02075 // }; 02076 // // .bwc. Mask out bit 6, use a multiplication op to write the 02077 // // resulting byte to each of the 4 bytes in temp, and xor the whole 02078 // // thing with bytes/st. 02079 // temp = ( (*c | ' ') * 16843009UL) ^ st; 02080 // bytes[0] = randomPermutation[cccc[0]]; 02081 // bytes[1] = randomPermutation[cccc[1]]; 02082 // bytes[2] = randomPermutation[cccc[2]]; 02083 // bytes[3] = randomPermutation[cccc[3]]; 02084 // } 02085 // 02086 // // convert from network to host byte order 02087 // return ntohl((u_long)st); 02088 } 02089 02090 Data 02091 bits(size_t v) 02092 { 02093 Data ret; 02094 for (unsigned int i = 0; i < 8*sizeof(size_t); ++i) 02095 { 02096 ret += ('0' + v%2); 02097 v /= 2; 02098 } 02099 02100 return ret; 02101 } 02102 02103 size_t 02104 Data::hash() const 02105 { 02106 return rawHash((const unsigned char*)(this->data()), this->size()); 02107 } 02108 02109 size_t 02110 Data::caseInsensitivehash() const 02111 { 02112 return rawCaseInsensitiveHash((const unsigned char*)(this->data()), this->size()); 02113 } 02114 02115 size_t 02116 Data::caseInsensitiveTokenHash() const 02117 { 02118 return rawCaseInsensitiveTokenHash((const unsigned char*)(this->data()), this->size()); 02119 } 02120 02121 #define compUnalignedRemainder(d1, d2, size) \ 02122 switch(size) \ 02123 {\ 02124 case 3: \ 02125 if( (*d1 ^ *d2) & 0xDF) \ 02126 { \ 02127 return false; \ 02128 } \ 02129 d1++; \ 02130 d2++; \ 02131 /* fallthrough */ \ 02132 case 2: \ 02133 if((get16bits(d1) ^ get16bits(d2)) & 0xDFDF) \ 02134 { \ 02135 return false; \ 02136 } \ 02137 d1+=2; \ 02138 d2+=2; \ 02139 break; \ 02140 case 1: \ 02141 if( (*d1 ^ *d2) & 0xDF) \ 02142 { \ 02143 return false; \ 02144 } \ 02145 d1++; \ 02146 d2++; \ 02147 /* fallthrough */ \ 02148 default: \ 02149 ; \ 02150 }\ 02151 02152 bool 02153 Data::sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const 02154 { 02155 assert(mSize==rhs.mSize); 02156 const char* d1(mBuf); 02157 const char* d2(rhs.mBuf); 02158 02159 if(mSize < 4) 02160 { 02161 // No point in trying 32-bit ops. 02162 compUnalignedRemainder(d1, d2, mSize); 02163 return true; 02164 } 02165 02166 int unalignedPrefix((ptrdiff_t)d1 & 3); 02167 02168 compUnalignedRemainder(d1, d2, unalignedPrefix); 02169 02170 // We are now on a 32-bit boundary with d1. 02171 UInt32* wd1((UInt32*)(d1)); 02172 size_t wordLen=(mSize-unalignedPrefix)>>2; 02173 int rem=(mSize-unalignedPrefix)&3; 02174 02175 if((ptrdiff_t)(d2)%4==0) 02176 { 02177 // d2 is aligned too. Happy day! 02178 UInt32* wd2((UInt32*)(d2)); 02179 for (;wordLen > 0; wordLen--) 02180 { 02181 // bitwise xor is zero iff equal, but we only really care about bits 02182 // other than bit 6, so we mask out bit 6 after the xor. 02183 if( (*wd1 ^ *wd2) & 0xDFDFDFDF) 02184 { 02185 return false; 02186 } 02187 wd1++; 02188 wd2++; 02189 } 02190 d2=(const char*)wd2; 02191 } 02192 else 02193 { 02194 for (;wordLen > 0; wordLen--) 02195 { 02196 // bitwise xor is zero iff equal, but we only really care about bits 02197 // other than bit 6, so we mask out bit 6 after the xor. 02198 UInt32 test=get32bits(d2); 02199 if( (*wd1 ^ test) & 0xDFDFDFDF) 02200 { 02201 return false; 02202 } 02203 wd1++; 02204 d2+=4; 02205 } 02206 } 02207 d1=(const char*)wd1; 02208 02209 compUnalignedRemainder(d1, d2, rem); 02210 return true; 02211 } 02212 02213 std::bitset<256> 02214 Data::toBitset(const resip::Data& chars) 02215 { 02216 std::bitset<256> result; 02217 result.reset(); 02218 for (unsigned int i=0; i!=chars.mSize;++i) 02219 { 02220 result.set(*(unsigned char*)(chars.mBuf+i)); 02221 } 02222 return result; 02223 } 02224 02225 std::ostream& 02226 Data::escapeToStream(std::ostream& str, 02227 const std::bitset<256>& shouldEscape) const 02228 { 02229 static char hex[] = "0123456789ABCDEF"; 02230 02231 if (empty()) 02232 { 02233 return str; 02234 } 02235 02236 const unsigned char* anchor = (unsigned char*)mBuf; 02237 const unsigned char* p = (unsigned char*)mBuf; 02238 const unsigned char* e = (unsigned char*)mBuf + mSize; 02239 02240 while (p < e) 02241 { 02242 // ?abr? Why is this special cased? Removing this code 02243 // does not change the behavior of this method. 02244 if (*p == '%' 02245 && e - p > 2 02246 && isHex(*(p+1)) 02247 && isHex(*(p+2))) 02248 { 02249 p+=3; 02250 } 02251 else if (shouldEscape[*p]) 02252 { 02253 if(p > anchor) 02254 { 02255 str.write((char*)anchor, p-anchor); 02256 } 02257 int hi = (*p & 0xF0)>>4; 02258 int low = (*p & 0x0F); 02259 02260 str << '%' << hex[hi] << hex[low]; 02261 anchor=++p; 02262 } 02263 else 02264 { 02265 ++p; 02266 } 02267 } 02268 if(p > anchor) 02269 { 02270 str.write((char*)anchor, p-anchor); 02271 } 02272 return str; 02273 } 02274 02275 HashValueImp(resip::Data, data.hash()); 02276 02277 static signed char base64Lookup[128] = 02278 { 02279 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 02280 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 02281 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 02282 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 02283 -1,-1,-1,62,-1,62,-2,63,52,53, 02284 54,55,56,57,58,59,60,61,-1,-1, 02285 -1,-2,-1,-1,-1,0, 1, 2, 3, 4, 02286 5, 6, 7, 8, 9, 10,11,12,13,14, 02287 15,16,17,18,19,20,21,22,23,24, 02288 25,-1,-1,-1,-1,63,-1,26,27,28, 02289 29,30,31,32,33,34,35,36,37,38, 02290 39,40,41,42,43,44,45,46,47,48, 02291 49,50,51,-1,-1,-1,-1,-1 02292 }; 02293 Data 02294 Data::base64decode() const 02295 { 02296 // see RFC 3548 02297 // this will decode normal and URL safe alphabet 02298 #if 0 02299 return Base64Coder::decode( *this ); 02300 #else 02301 int wc=0; 02302 int val=0; 02303 Data bin; 02304 bin.reserve( size()*3/4 ); 02305 02306 for( unsigned int i=0; i<size(); i++ ) 02307 { 02308 unsigned int x = mBuf[i] & 0x7F; 02309 char c1,c2,c3; 02310 02311 int v = base64Lookup[x]; 02312 02313 if ( v >= 0 ) 02314 { 02315 val = val << 6; 02316 val |= v; 02317 wc++; 02318 02319 if ( wc == 4 ) 02320 { 02321 c3 = char( val & 0xFF ); val = val >> 8; 02322 c2 = char( val & 0xFF ); val = val >> 8; 02323 c1 = char( val & 0xFF ); val = val >> 8; 02324 02325 bin += c1; 02326 bin += c2; 02327 bin += c3; 02328 02329 wc=0; 02330 val=0; 02331 } 02332 } 02333 if ( base64Lookup[x] == -2 ) 02334 { 02335 if (wc==2) val = val<<12; 02336 if (wc==3) val = val<<6; 02337 02338 c3 = char( val & 0xFF ); val = val >> 8; 02339 c2 = char( val & 0xFF ); val = val >> 8; 02340 c1 = char( val & 0xFF ); val = val >> 8; 02341 02342 unsigned int xNext = mBuf[i] & 0x7F; 02343 if ( (i+1<size() ) && ( base64Lookup[xNext] == -2 )) 02344 { 02345 bin += c1; 02346 i++; 02347 } 02348 else 02349 { 02350 bin += c1; 02351 bin += c2; 02352 } 02353 02354 break; 02355 } 02356 } 02357 02358 return bin; 02359 #endif 02360 } 02361 02362 02363 // see RFC 3548 02364 static unsigned char codeCharUnsafe[] = 02365 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 02366 static unsigned char codeCharSafe[] = 02367 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."; 02368 Data 02369 Data::base64encode(bool useSafeSet) const 02370 { 02371 unsigned char* codeChar = useSafeSet ? codeCharSafe : codeCharUnsafe; 02372 02373 int srcLength = (int)this->size(); 02374 unsigned int dstLimitLength = srcLength*4/3 + 1 + 2; // +2 for the == chars 02375 unsigned char * dstData = new unsigned char[dstLimitLength]; 02376 unsigned int dstIndex = 0; 02377 02378 const char * p = static_cast<const char *>( this->data() ); 02379 02380 for(int index=0;index<srcLength;index+=3) 02381 { 02382 unsigned char codeBits = (p[index] & 0xfc)>>2; 02383 02384 assert(codeBits < 64); 02385 dstData[dstIndex++] = codeChar[codeBits]; // c0 output 02386 assert(dstIndex <= dstLimitLength); 02387 02388 // do second codeBits 02389 codeBits = ((p[index]&0x3)<<4); 02390 if (index+1 < srcLength) 02391 { 02392 codeBits |= ((p[index+1]&0xf0)>>4); 02393 } 02394 assert(codeBits < 64); 02395 dstData[dstIndex++] = codeChar[codeBits]; // c1 output 02396 assert(dstIndex <= dstLimitLength); 02397 02398 if (index+1 >= srcLength) 02399 { 02400 dstData[dstIndex++] = codeChar[64]; 02401 assert(dstIndex <= dstLimitLength); 02402 dstData[dstIndex++] = codeChar[64]; 02403 assert(dstIndex <= dstLimitLength); 02404 break; // encoded d0 only 02405 } 02406 02407 // do third codeBits 02408 codeBits = ((p[index+1]&0xf)<<2); 02409 if (index+2 < srcLength) 02410 { 02411 codeBits |= ((p[index+2]&0xc0)>>6); 02412 } 02413 assert(codeBits < 64); 02414 dstData[dstIndex++] = codeChar[codeBits]; // c2 output 02415 assert(dstIndex <= dstLimitLength); 02416 02417 if (index+2 >= srcLength) 02418 { 02419 dstData[dstIndex++] = codeChar[64]; 02420 assert(dstIndex <= dstLimitLength); 02421 break; // encoded d0 d1 only 02422 } 02423 02424 // do fourth codeBits 02425 codeBits = ((p[index+2]&0x3f)); 02426 assert(codeBits < 64); 02427 dstData[dstIndex++] = codeChar[codeBits]; // c3 output 02428 assert(dstIndex <= dstLimitLength); 02429 // outputed all d0,d1, and d2 02430 } 02431 02432 return Data(Data::Take, reinterpret_cast<char*>(dstData), 02433 dstIndex); 02434 } 02435 02436 02437 /* ==================================================================== 02438 * The Vovida Software License, Version 1.0 02439 * 02440 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 02441 * 02442 * Redistribution and use in source and binary forms, with or without 02443 * modification, are permitted provided that the following conditions 02444 * are met: 02445 * 02446 * 1. Redistributions of source code must retain the above copyright 02447 * notice, this list of conditions and the following disclaimer. 02448 * 02449 * 2. Redistributions in binary form must reproduce the above copyright 02450 * notice, this list of conditions and the following disclaimer in 02451 * the documentation and/or other materials provided with the 02452 02453 * distribution. 02454 * 02455 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 02456 * and "Vovida Open Communication Application Library (VOCAL)" must 02457 * not be used to endorse or promote products derived from this 02458 * software without prior written permission. For written 02459 * permission, please contact vocal@vovida.org. 02460 * 02461 * 4. Products derived from this software may not be called "VOCAL", nor 02462 * may "VOCAL" appear in their name, without prior written 02463 * permission of Vovida Networks, Inc. 02464 * 02465 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 02466 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 02467 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 02468 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 02469 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 02470 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 02471 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 02472 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 02473 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 02474 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 02475 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 02476 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 02477 * DAMAGE. 02478 * 02479 * ==================================================================== 02480 * 02481 * This software consists of voluntary contributions made by Vovida 02482 * Networks, Inc. and many individuals on behalf of Vovida Networks, 02483 * Inc. For more information on Vovida Networks, Inc., please see 02484 * <http://www.vovida.org/>. 02485 * 02486 * vi: set shiftwidth=3 expandtab: 02487 */
1.7.5.1