reSIProcate/rutil  9694
Data.hxx
Go to the documentation of this file.
00001 #ifndef RESIP_Data_hxx
00002 #define RESIP_Data_hxx
00003 
00004 #ifdef HAVE_CONFIG_H
00005 #include "config.h"
00006 #endif
00007 
00008 #include <iostream>
00009 #include <string>
00010 #include <bitset>
00011 #include <cassert>
00012 
00013 #include "rutil/compat.hxx"
00014 #include "rutil/DataStream.hxx"
00015 #include "rutil/HeapInstanceCounter.hxx"
00016 #include "rutil/HashMap.hxx"
00017 
00018 #ifndef RESIP_DATA_LOCAL_SIZE
00019 #define RESIP_DATA_LOCAL_SIZE 16
00020 #endif
00021 
00022 class TestData;
00023 namespace resip
00024 {
00025 
00038 template <int S>
00039 struct DataLocalSize
00040 {
00041       explicit DataLocalSize(size_t) {}
00042 };
00043 
00044 // .bwc. Pack class Data; has to come before doxygen block though.
00045 #pragma pack(4)
00046 
00086 class Data 
00087 {
00088    public:
00089       RESIP_HeapCount(Data);
00090 
00091       typedef UInt32 size_type;
00092 
00093       inline Data()
00094          : mBuf(mPreBuffer),
00095            mSize(0),
00096            mCapacity(LocalAlloc),
00097            mShareEnum(Borrow)
00098       {
00099          mBuf[mSize] = 0;
00100       }
00101 
00105       class PreallocateType
00106       {
00107          friend class Data;
00108          explicit PreallocateType(int);
00109       };
00113       static const PreallocateType Preallocate;
00114 
00125       Data(size_type capacity, const PreallocateType&);
00126 
00127 //#define DEPRECATED_PREALLOC
00128 #ifdef DEPRECATED_PREALLOC
00129 
00148       Data(size_type capacity, bool foo);
00149 #endif      
00150 
00158       Data(const char* str);
00159 
00165       Data(const char* buffer, size_type length);
00166 
00172       Data(const unsigned char* buffer, size_type length);
00173 
00174       Data(const Data& data);
00175 
00176 #ifdef RESIP_HAS_RVALUE_REFS
00177       Data(Data &&data);
00178 #endif
00179 
00182       explicit Data(const std::string& str);
00183 
00190       explicit Data(int value);
00191 
00198       explicit Data(unsigned long value);
00199 
00206       explicit Data(unsigned int value);
00207 
00214       explicit Data(UInt64 value);
00215 
00216 #ifndef RESIP_FIXED_POINT
00217       enum DoubleDigitPrecision 
00218       {
00219          ZeroDigitPrecision = 0, OneDigitPrecision, 
00220          TwoDigitPrecision, ThreeDigitPrecision, 
00221          FourDigitPrecision, FiveDigitPrecision,
00222          SixDigitPrecision, SevenDigitPrecision,
00223          EightDigitPrecision, NineDigitPrecision,
00224          TenDigitPrecision, MaxDigitPrecision
00225       };
00235       explicit Data(double value, 
00236                     Data::DoubleDigitPrecision precision = FourDigitPrecision);
00237 #endif
00238 
00243       explicit Data(bool value);
00244 
00249       explicit Data(char c);
00250 
00254       enum ShareEnum 
00255       {
00260         Borrow=0,
00261 
00266         Share=1,
00267 
00272         Take=2
00273       };
00274 
00281       Data(ShareEnum, const char* buffer, size_type length);
00282 
00291       Data(ShareEnum, const char* buffer);
00292 
00306       Data(ShareEnum, const Data& staticData); // Cannot call with 'Take'
00307 
00308       inline ~Data()
00309       {
00310          if (mShareEnum == Take)
00311          {
00312             delete[] mBuf;
00313          }
00314       }
00315 
00327       Data& setBuf(ShareEnum se, const char *buf, size_type length);
00328 
00333       Data& setBuf(ShareEnum se, const char *str)
00334       {
00335          return setBuf(se, str, (size_type)strlen(str));
00336       };
00337 
00338 
00346       Data& takeBuf(Data& other);
00347 
00358       Data& copy(const char *buf, size_type length);
00359 
00375       char* getBuf(size_type length);
00376 
00381       template<class T>
00382       static Data from(const T& x)
00383       {
00384          Data d;
00385          {
00386             DataStream s(d);
00387             s << x;
00388          }
00389          return d;
00390       }
00391 
00392       friend bool operator==(const Data& lhs, const Data& rhs);
00393       friend bool operator==(const Data& lhs, const char* rhs);
00394 
00395       friend bool operator<(const Data& lhs, const Data& rhs);
00396       friend bool operator<(const Data& lhs, const char* rhs);
00397       friend bool operator<(const char* lhs, const Data& rhs);
00398 
00399       Data& operator=(const Data& data)
00400       {
00401          if (&data==this)
00402              return *this;
00403          return copy(data.mBuf,data.mSize);
00404       }
00405 
00406 #ifdef RESIP_HAS_RVALUE_REFS
00407       Data& operator=(Data &&data);
00408 #endif
00409 
00418       Data& operator=(const char* str)
00419       {
00420          return copy(str, (size_type)strlen(str));
00421       }
00422 
00426       Data operator+(const Data& rhs) const;
00427 
00434       Data operator+(const char* str) const;
00435 
00439       Data operator+(char c) const;
00440 
00444       inline Data& operator+=(const Data& rhs)
00445       {
00446          return append(rhs.data(), rhs.size());
00447       }
00448 
00456       inline Data& operator+=(const char* str)
00457       {
00458          assert(str);
00459          return append(str, (size_type)strlen(str));
00460       }
00461 
00462 
00466       inline Data& operator+=(char c)
00467       {
00468          return append(&c, 1);
00469       }
00470 
00471 
00478       Data& operator^=(const Data& rhs);
00479 
00484       inline char& operator[](size_type p)
00485       {
00486          assert(p < mSize);
00487          own();
00488          return mBuf[p];
00489       }
00490 
00494       inline char operator[](size_type p) const
00495       {
00496          assert(p < mSize);
00497          return mBuf[p];
00498       }
00499 
00503       char& at(size_type p);
00504 
00510       void reserve(size_type capacity);
00511 
00516       Data& append(const char* str, size_type len);
00517 
00529       size_type truncate(size_type len);
00530 
00538       Data& truncate2(size_type len);
00539 
00543       bool empty() const { return mSize == 0; }
00544 
00551       size_type size() const { return mSize; }
00552 
00560       inline const char* data() const
00561       {
00562          return mBuf;
00563       }
00564 
00577       const char* c_str() const;
00578 
00582       inline const char* begin() const
00583       {
00584          return mBuf;
00585       }
00586 
00590       inline const char* end() const
00591       {
00592          return mBuf + mSize;
00593       }
00594 
00595       typedef enum
00596       {
00597          BINARY,
00598          BASE64,
00599          HEX
00600       } EncodingType;
00601 
00607       Data md5(EncodingType type=HEX) const;
00608 
00614       Data& lowercase();
00615 
00621       Data& uppercase();
00622 
00637       Data& schemeLowercase();
00638 
00643       Data hex() const;
00644 
00652       Data escaped() const;
00653 
00665       Data charEncoded() const;
00666 
00681       Data charUnencoded() const;
00682 
00686       Data urlEncoded() const;
00687 
00691       Data urlDecoded() const;
00692 
00696       EncodeStream& urlEncode(EncodeStream& s) const;
00697 
00701       EncodeStream& urlDecode(EncodeStream& s) const;
00702 
00706       Data xmlCharDataEncode() const;
00707 
00711       Data xmlCharDataDecode() const;
00712 
00716       EncodeStream& xmlCharDataEncode(EncodeStream& s) const;
00717 
00721       EncodeStream& xmlCharDataDecode(EncodeStream& s) const;
00722 
00728       Data trunc(size_type trunc) const;
00729 
00735       Data& clear() { return truncate2(0); };
00736 
00743       int convertInt() const;
00744       unsigned long convertUnsignedLong() const;
00745 
00751       size_t convertSize() const;
00752 
00753 #ifndef RESIP_FIXED_POINT
00754 
00761       double convertDouble() const;
00762 #endif
00763 
00769       UInt64 convertUInt64() const;
00770 
00777       bool prefix(const Data& pre) const;
00778 
00785       bool postfix(const Data& post) const;
00786 
00793       Data substr(size_type first, size_type count = Data::npos) const;
00794 
00804       size_type find(const Data& match, size_type start = 0) const;
00805 
00810       int replace(const Data& match, const Data& target, int max=INT_MAX);
00811       
00815       static const Data Empty;
00816 
00820       static const size_type npos;
00821 
00827       static bool init(DataLocalSize<RESIP_DATA_LOCAL_SIZE> arg);
00828 
00834       Data base64decode() const;
00835 
00841       Data base64encode(bool useUrlSafe=false) const;
00842 
00850       static size_t rawHash(const unsigned char* c, size_t size);
00851 
00855       size_t hash() const;
00856 
00864       static size_t rawCaseInsensitiveHash(const unsigned char* c, size_t size);
00865 
00875       static size_t rawCaseInsensitiveTokenHash(const unsigned char* c, size_t size);
00876 
00881       size_t caseInsensitivehash() const;
00882 
00889       size_t caseInsensitiveTokenHash() const;
00890 
00891       inline bool caseInsensitiveTokenCompare(const Data& rhs) const
00892       {
00893          if(mSize==rhs.mSize)
00894          {
00895             return sizeEqualCaseInsensitiveTokenCompare(rhs);
00896          }
00897          return false;
00898       }
00899 
00900       bool sizeEqualCaseInsensitiveTokenCompare(const Data& rhs) const;
00901 
00907       static std::bitset<256> toBitset(const resip::Data& chars);
00908 
00923       template<class Predicate> EncodeStream& 
00924           escapeToStream(EncodeStream& str, 
00925                          Predicate shouldEscape) const;
00926 
00935       std::ostream& escapeToStream(std::ostream& str, 
00936                                    const std::bitset<256>& shouldEscape) const;
00937 
00938    private:
00942       Data(const char* buffer, size_type length, bool);
00943 
00948       void own() const;
00949 
00953       void resize(size_type newSize, bool copy);
00954 
00955       static bool isHex(unsigned char c);      
00956 
00960       enum {LocalAlloc = RESIP_DATA_LOCAL_SIZE };
00961 
00962       char* mBuf;
00963       size_type mSize;
00964       size_type mCapacity;
00965       char mPreBuffer[LocalAlloc];
00966       // Null terminator for mPreBuffer when mSize==LocalAlloc lands here; this
00967       // is ok, because Borrow==0.
00968       // Note: we could use a char here, and expand mPreBuffer by 3 bytes, but 
00969       // this imposes a performance penalty since it requires operating on a 
00970       // memory location smaller than a word (requires masking and such).
00971       size_type mShareEnum;
00972 
00973       friend std::ostream& operator<<(std::ostream& strm, const Data& d);
00974 #ifndef RESIP_USE_STL_STREAMS
00975       friend EncodeStream& operator<<(EncodeStream& strm, const Data& d);
00976 #endif
00977       friend class ParseBuffer;
00978       friend class DataBuffer;
00979       friend class DataStream;
00980       friend class oDataStream;
00981       friend class ::TestData;
00982       friend class MD5Buffer;
00983 };
00984 // reset alignment to default
00985 #pragma pack()
00986 
00987 
00988 class DataHelper {
00989    public:
00990       static const bool isCharHex[256];
00991 };
00992 
00993 static bool invokeDataInit = Data::init(DataLocalSize<RESIP_DATA_LOCAL_SIZE>(0));
00994 
00995 inline bool Data::isHex(unsigned char c)
00996 {
00997    return DataHelper::isCharHex[c];
00998 }
00999 
01000 inline bool isEqualNoCase(const Data& left, const Data& right)
01001 {
01002    return ( (left.size() == right.size()) &&
01003             (strncasecmp(left.data(), right.data(), left.size()) == 0) );
01004 }
01005 
01006 inline bool isTokenEqualNoCase(const Data& left, const Data& right)
01007 {
01008    return left.caseInsensitiveTokenCompare(right);
01009 }
01010 
01011 inline bool isLessThanNoCase(const Data& left, const Data& right)
01012 {
01013    size_t minsize = resipMin( left.size(), right.size() );
01014    int res = strncasecmp(left.data(), right.data(), minsize);
01015 
01016    if (res < 0)
01017    {
01018       return true;
01019    }
01020    else if (res > 0)
01021    {
01022       return false;
01023    }
01024    else
01025    {
01026       return left.size() < right.size();
01027    }
01028 }
01029 
01030 template<class Predicate> EncodeStream& 
01031 Data::escapeToStream(EncodeStream& str, Predicate shouldEscape) const
01032 {
01033    static char hex[] = "0123456789ABCDEF";
01034 
01035    if (empty())
01036    {
01037       return str;
01038    }
01039    
01040    const unsigned char* p = (unsigned char*)mBuf;
01041    const unsigned char* e = (unsigned char*)mBuf + mSize;
01042 
01043    while (p < e)
01044    {
01045       // ?abr? Why is this special cased? Removing this code
01046       // does not change the behavior of this method.
01047       if (*p == '%' 
01048           && e - p > 2 
01049           && isHex(*(p+1)) 
01050           && isHex(*(p+2)))
01051       {
01052          str.write((char*)p, 3);
01053          p+=3;
01054       }
01055       else if (shouldEscape[*p])
01056       {
01057          int hi = (*p & 0xF0)>>4;
01058          int low = (*p & 0x0F);
01059 
01060          str << '%' << hex[hi] << hex[low];
01061          p++;
01062       }
01063       else
01064       {
01065          str.put(*p++);
01066       }
01067    }
01068    return str;
01069 }
01070 
01071 inline bool operator!=(const Data& lhs, const Data& rhs) { return !(lhs == rhs); }
01072 inline bool operator>(const Data& lhs, const Data& rhs) { return rhs < lhs; }
01073 inline bool operator<=(const Data& lhs, const Data& rhs) { return !(rhs < lhs); }
01074 inline bool operator>=(const Data& lhs, const Data& rhs) { return !(lhs < rhs); }
01075 inline bool operator!=(const Data& lhs, const char* rhs) { return !(lhs == rhs); }
01076 inline bool operator>(const Data& lhs, const char* rhs) { return rhs < lhs; }
01077 inline bool operator<=(const Data& lhs, const char* rhs) { return !(rhs < lhs); }
01078 inline bool operator>=(const Data& lhs, const char* rhs) { return !(lhs < rhs); }
01079 inline bool operator==(const char* lhs, const Data& rhs) { return rhs == lhs; }
01080 inline bool operator!=(const char* lhs, const Data& rhs) { return !(rhs == lhs); }
01081 inline bool operator>(const char* lhs, const Data& rhs) { return rhs < lhs; }
01082 inline bool operator<=(const char* lhs, const Data& rhs) { return !(rhs < lhs); }
01083 inline bool operator>=(const char* lhs, const Data& rhs) { return !(lhs < rhs); }
01084 #ifndef  RESIP_USE_STL_STREAMS
01085 EncodeStream& operator<<(EncodeStream& strm, const Data& d);
01086 #endif
01087 inline std::ostream& operator<<(std::ostream& strm, const Data& d)
01088 {
01089    return strm.write(d.mBuf, d.mSize);
01090 }
01091 
01092 
01093 inline Data
01094 operator+(const char* c, const Data& d)
01095 {
01096    return Data(c) + d;
01097 }
01098 
01099 }
01100 
01101 HashValue(resip::Data);
01102 
01103 #endif
01104 
01105 /* ====================================================================
01106  * The Vovida Software License, Version 1.0 
01107  * 
01108  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
01109  * 
01110  * Redistribution and use in source and binary forms, with or without
01111  * modification, are permitted provided that the following conditions
01112  * are met:
01113  * 
01114  * 1. Redistributions of source code must retain the above copyright
01115  *    notice, this list of conditions and the following disclaimer.
01116  * 
01117  * 2. Redistributions in binary form must reproduce the above copyright
01118  *    notice, this list of conditions and the following disclaimer in
01119  *    the documentation and/or other materials provided with the
01120  *    distribution.
01121  * 
01122  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
01123  *    and "Vovida Open Communication Application Library (VOCAL)" must
01124  *    not be used to endorse or promote products derived from this
01125  *    software without prior written permission. For written
01126  *    permission, please contact vocal@vovida.org.
01127  *
01128  * 4. Products derived from this software may not be called "VOCAL", nor
01129  *    may "VOCAL" appear in their name, without prior written
01130  *    permission of Vovida Networks, Inc.
01131  * 
01132  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
01133  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
01134  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
01135  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
01136  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
01137  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
01138  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
01139  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
01140  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
01141  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
01142  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01143  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
01144  * DAMAGE.
01145  * 
01146  * ====================================================================
01147  * 
01148  * This software consists of voluntary contributions made by Vovida
01149  * Networks, Inc. and many individuals on behalf of Vovida Networks,
01150  * Inc.  For more information on Vovida Networks, Inc., please see
01151  * <http://www.vovida.org/>.
01152  *
01153  * vi: set shiftwidth=3 expandtab:
01154  */