reSIProcate/rutil  9694
ParseBuffer.hxx
Go to the documentation of this file.
00001 #if !defined(RESIP_PARSEBUFFER_HXX)
00002 #define RESIP_PARSEBUFFER_HXX 
00003 
00004 #include "rutil/Data.hxx"
00005 #include "rutil/ParseException.hxx"
00006 
00007 namespace resip
00008 {
00009 
00017 class ParseBuffer
00018 {
00019    public:
00020       // does NOT OWN the buffer memory
00021       ParseBuffer(const char* buff, size_t len, 
00022                   const Data& errorContext = Data::Empty);
00023 
00024       explicit ParseBuffer(const Data& data,
00025                            const Data& errorContext = Data::Empty);
00026 
00027       ParseBuffer(const ParseBuffer& other);
00028 
00030       // .bwc. Backwards-compatibility hack; ParseException used to be
00031       // a full inner class of ParseBuffer, and we also had a separate 
00032       // ParseException class that other things used. For consistency, we have
00033       // moved everything over to use ParseException, but there is app-code
00034       // out there that still expects ParseException to exist.
00035       typedef ParseException Exception;
00037 
00038    private:
00045       class CurrentPosition
00046       {
00047          public:
00048             inline explicit CurrentPosition(const ParseBuffer& pb) :
00049                mPb(pb)
00050             {}
00051 
00052             operator const char*() const
00053             {
00054                return mPb.mPosition;
00055             }
00056 
00057             const char& operator*() const
00058             {
00059                mPb.assertNotEof();
00060                return *mPb.mPosition;
00061             }
00062 
00063             const ParseBuffer& mPb;
00064       };
00065 
00071       class Pointer
00072       {
00073          public:
00074             Pointer(const ParseBuffer& pb,
00075                     const char* position,
00076                     bool atEof);
00077             Pointer(const CurrentPosition& pos);
00078 
00079             operator const char*() const
00080             {
00081                return mPosition;
00082             }
00083 
00084             const char& operator*() const;
00085          private:
00086             const ParseBuffer& mPb;
00087             const char* mPosition;
00088             const bool mIsValid;
00089             static const Data msg;
00090       };
00091 
00092    public:
00093       const Data& getContext() const {return mErrorContext;}
00094       
00095       // allow the buffer to be rolled back
00096       ParseBuffer& operator=(const ParseBuffer& other);
00097       void reset(const char* pos)
00098       {
00099          assert( mBuff <= mEnd);
00100          assert( (pos >= mBuff) && (pos <= mEnd) );
00101          mPosition = pos;
00102       }
00103 
00104       // abcdef
00105       // ^     ^
00106       // begin end
00107       bool eof() const { return mPosition >= mEnd;}
00108       bool bof() const { return mPosition <= mBuff;}
00109       bool valid() const {return (!eof()) && (!bof());}
00110       Pointer start() const { return Pointer(*this, mBuff, eof()); }
00111       CurrentPosition position() const { return CurrentPosition(*this); }
00112       Pointer end() const { return Pointer(*this, mEnd, true); }
00113 
00114       CurrentPosition skipChar()
00115       {
00116          if (eof())
00117          {
00118             fail(__FILE__, __LINE__,"skipped over eof");
00119          }
00120          ++mPosition;
00121          return CurrentPosition(*this);
00122       }
00123 
00124       CurrentPosition skipChar(char c);
00125       CurrentPosition skipChars(const char* cs);
00126       CurrentPosition skipChars(const Data& cs);
00127       CurrentPosition skipNonWhitespace();
00128       CurrentPosition skipWhitespace();
00129       CurrentPosition skipLWS();
00130       CurrentPosition skipToTermCRLF();
00131       CurrentPosition skipToChar(char c)
00132       {
00133          mPosition = (const char*)memchr(mPosition, c, mEnd-mPosition);
00134          if(!mPosition)
00135          {
00136             mPosition=mEnd;
00137          }
00138          return CurrentPosition(*this);
00139       }
00140       CurrentPosition skipToChars(const char* cs);
00141       CurrentPosition skipToChars(const Data& cs); // ?dlb? case sensitivity arg?
00142       CurrentPosition skipToOneOf(const char* cs);
00143       CurrentPosition skipToOneOf(const char* cs1, const char* cs2);
00144       CurrentPosition skipToOneOf(const Data& cs);
00145       CurrentPosition skipToOneOf(const Data& cs1, const Data& cs2);
00146 
00147       // std::bitset based parse function
00148       CurrentPosition skipChars(const std::bitset<256>& cs)
00149       {
00150          while (mPosition < mEnd)
00151          {
00152             if (cs.test((unsigned char)(*mPosition)))
00153             {
00154                mPosition++;
00155             }
00156             else
00157             {
00158                return CurrentPosition(*this);
00159             }
00160          }
00161          return CurrentPosition(*this);
00162       }
00163 
00164       CurrentPosition skipToOneOf(const std::bitset<256>& cs)
00165       {
00166          while (mPosition < mEnd)
00167          {
00168             if (cs.test((unsigned char)(*mPosition)))
00169             {
00170                return CurrentPosition(*this);
00171             }
00172             else
00173             {
00174                mPosition++;
00175             }
00176          }
00177          return CurrentPosition(*this);
00178       }
00179 
00180       const char* skipToEndQuote(char quote = '"');
00181       CurrentPosition skipN(int count)
00182       {
00183          mPosition += count;
00184          if (mPosition > mEnd)
00185          {
00186             fail(__FILE__, __LINE__, "skipped eof");
00187          }
00188          return CurrentPosition(*this);
00189       }
00190 
00191       CurrentPosition skipToEnd()
00192       {
00193          mPosition = mEnd;
00194          return CurrentPosition(*this);
00195       }
00196 
00197       // inverse of skipChar() -- end up at char not before it
00198       const char* skipBackChar();
00199       const char* skipBackWhitespace();
00200       const char* skipBackN(int count)
00201       {
00202          mPosition -= count;
00203          if (bof())
00204          { 
00205            fail(__FILE__, __LINE__,"backed over beginning of buffer");
00206          }
00207          return mPosition;
00208       }
00209 
00210       const char* skipBackChar(char c);
00211       const char* skipBackToChar(char c);
00212       const char* skipBackToOneOf(const char* cs);
00213 
00214       void assertEof() const
00215       {
00216          if (!eof())
00217          {
00218             fail(__FILE__, __LINE__,"expected eof");
00219          }
00220       }
00221 
00222       void assertNotEof() const
00223       {
00224          if (eof())
00225          {
00226             fail(__FILE__, __LINE__,"unexpected eof");
00227          }
00228       }
00229 
00230       void fail(const char* file, unsigned int line,
00231                 const Data& errmsg = Data::Empty) const;
00232 
00234       void data(Data& data, const char* start) const;
00235 
00236       Data data(const char* start) const;
00237 
00238       void dataUnescaped(Data& data, const char* start) const;      
00239       
00240       int integer();
00241 
00242       
00243       UInt8 uInt8();
00244       UInt32 uInt32();
00245       UInt64 uInt64();
00246 
00247       RESIP_DEPRECATED UInt64 unsignedLongLong(){return uInt64();} 
00248       RESIP_DEPRECATED unsigned long unsignedInteger(){return uInt32();}
00249 
00250 #ifndef RESIP_FIXED_POINT               
00251       float floatVal();
00252 #endif
00253       int qVal();
00254 
00255       static bool oneOf(char c, const char* cs);
00256       static bool oneOf(char c, const Data& cs);
00257       static const char* Whitespace;
00258       static const char* ParamTerm;
00259    private:
00260       friend class ParseBuffer::CurrentPosition;
00261       const char* mBuff;
00262       const char* mPosition;
00263       const char* mEnd;
00264       const Data& mErrorContext;
00265 };
00266 
00267 }
00268 
00269 #endif
00270 
00271 /* ====================================================================
00272  * The Vovida Software License, Version 1.0 
00273  * 
00274  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00275  * 
00276  * Redistribution and use in source and binary forms, with or without
00277  * modification, are permitted provided that the following conditions
00278  * are met:
00279  * 
00280  * 1. Redistributions of source code must retain the above copyright
00281  *    notice, this list of conditions and the following disclaimer.
00282  * 
00283  * 2. Redistributions in binary form must reproduce the above copyright
00284  *    notice, this list of conditions and the following disclaimer in
00285  *    the documentation and/or other materials provided with the
00286  *    distribution.
00287  * 
00288  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00289  *    and "Vovida Open Communication Application Library (VOCAL)" must
00290  *    not be used to endorse or promote products derived from this
00291  *    software without prior written permission. For written
00292  *    permission, please contact vocal@vovida.org.
00293  *
00294  * 4. Products derived from this software may not be called "VOCAL", nor
00295  *    may "VOCAL" appear in their name, without prior written
00296  *    permission of Vovida Networks, Inc.
00297  * 
00298  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00299  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00300  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00301  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00302  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00303  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00304  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00305  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00306  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00307  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00308  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00309  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00310  * DAMAGE.
00311  * 
00312  * ====================================================================
00313  * 
00314  * This software consists of voluntary contributions made by Vovida
00315  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00316  * Inc.  For more information on Vovida Networks, Inc., please see
00317  * <http://www.vovida.org/>.
00318  *
00319  */