reSIProcate/rutil  9694
Data.cxx
Go to the documentation of this file.
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 << "&amp;";
01427          break;
01428       case '<':
01429          s << "&lt;";
01430          break;
01431       case '>':
01432          s << "&gt;";
01433          break;
01434       case '\'':
01435          s << "&apos;";
01436          break;
01437       case '\"':
01438          s << "&quot;";
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  */