reSIProcate/stack  9694
ParserContainer.hxx
Go to the documentation of this file.
00001 #ifndef RESIP_ParserContainer_hxx
00002 #define RESIP_ParserContainer_hxx
00003 
00004 #include <algorithm>
00005 #include <iterator>
00006 
00007 #include "resip/stack/HeaderFieldValueList.hxx"
00008 #include "resip/stack/ParserContainerBase.hxx"
00009 
00010 namespace resip
00011 {
00012 using std::ptrdiff_t;
00021 template<class T>
00022 class ParserContainer : public ParserContainerBase
00023 {
00024    public:
00025       typedef T value_type;
00026       typedef value_type* pointer;
00027       typedef const value_type* const_pointer;
00028       typedef value_type& reference;
00029       typedef const value_type& const_reference;
00030       typedef ptrdiff_t difference_type;
00031 
00035       ParserContainer()
00036          : ParserContainerBase(Headers::UNKNOWN)
00037       {}
00038       
00039       ParserContainer(PoolBase& pool)
00040          : ParserContainerBase(Headers::UNKNOWN,pool)
00041       {}
00042       
00048       ParserContainer(HeaderFieldValueList* hfvs,
00049                       Headers::Type type = Headers::UNKNOWN)
00050          : ParserContainerBase(type)
00051       {
00052          mParsers.reserve(hfvs->size());
00053          for (HeaderFieldValueList::iterator i = hfvs->begin();
00054               i != hfvs->end(); i++)
00055          {
00056             // create, store without copying -- 
00057             // keeps the HeaderFieldValue from reallocating its buffer
00058             mParsers.push_back(HeaderKit::Empty);
00059             mParsers.back().hfv.init(i->getBuffer(),i->getLength(),false);
00060          }
00061       }
00062 
00063       ParserContainer(HeaderFieldValueList* hfvs,
00064                       Headers::Type type,
00065                       PoolBase& pool)
00066          : ParserContainerBase(type,pool)
00067       {
00068          mParsers.reserve(hfvs->size());
00069          for (HeaderFieldValueList::iterator i = hfvs->begin();
00070               i != hfvs->end(); i++)
00071          {
00072             // create, store without copying -- 
00073             // keeps the HeaderFieldValue from reallocating its buffer
00074             mParsers.push_back(HeaderKit::Empty);
00075             mParsers.back().hfv.init(i->getBuffer(),i->getLength(),false);
00076          }
00077       }
00078 
00082       ParserContainer(const ParserContainer& other)
00083          : ParserContainerBase(other)
00084       {}
00085 
00089       ParserContainer(const ParserContainer& other, PoolBase& pool)
00090          : ParserContainerBase(other, pool)
00091       {}
00092 
00096       ParserContainer& operator=(const ParserContainer& other)
00097       {
00098          return static_cast<ParserContainer&>(ParserContainerBase::operator=(other));
00099       }
00100 
00104       T& front() 
00105       {
00106          return ensureInitialized(mParsers.front(),this);
00107       }
00108       
00112       T& back() 
00113       { 
00114          return ensureInitialized(mParsers.back(),this);
00115       }
00116       
00120       const T& front() const 
00121       { 
00122          return ensureInitialized(mParsers.front(),this);
00123       }
00124       
00128       const T& back() const 
00129       { 
00130          return ensureInitialized(mParsers.back(),this);
00131       }
00132       
00136       void push_front(const T & t) 
00137       { 
00138          mParsers.insert(mParsers.begin(), HeaderKit::Empty);
00139          mParsers.front().pc=makeParser(t);
00140       }
00141 
00145       void push_back(const T & t) 
00146       { 
00147          mParsers.push_back(HeaderKit::Empty);
00148          mParsers.back().pc=makeParser(t);
00149       }
00150             
00155       ParserContainer reverse() const
00156       {
00157          ParserContainer tmp(*this);
00158          std::reverse(tmp.mParsers.begin(), tmp.mParsers.end());
00159          return tmp;
00160       }
00161 
00162       typedef ParserContainerBase::Parsers Parsers;
00163       // .dlb. these can be partially hoisted as well
00164       class const_iterator;
00165       
00169       class iterator : public std::iterator<std::bidirectional_iterator_tag, T>
00170       {
00171          public:
00172             iterator(typename Parsers::iterator i,ParserContainer* ref) : mIt(i),mRef(ref){}
00173             iterator() : mRef(0) {}
00174             iterator(const iterator& orig) : mIt(orig.mIt), mRef(orig.mRef) {}
00175 
00176             iterator operator++() {iterator it(++mIt,mRef); return it;}
00177             iterator operator++(int) {iterator it(mIt++,mRef); return it;}
00178             iterator operator--() {iterator it(--mIt,mRef); return it;}
00179             iterator operator--(int) {iterator it(mIt--,mRef); return it;}
00180             bool operator!=(const iterator& rhs) { return mIt != rhs.mIt; }
00181             bool operator==(const iterator& rhs) { return mIt == rhs.mIt; }
00182             bool operator!=(const const_iterator& rhs) { return mIt != rhs.mIt; }
00183             bool operator==(const const_iterator& rhs) { return mIt == rhs.mIt; }
00184             iterator& operator=(const iterator& rhs) 
00185             {
00186                mIt = rhs.mIt; 
00187                mRef = rhs.mRef;
00188                return *this;
00189             }
00190             T& operator*() {return ensureInitialized(*mIt,mRef);}
00191             T* operator->() {return &ensureInitialized(*mIt,mRef);}
00192          private:
00193             typename Parsers::iterator mIt;
00194             ParserContainer* mRef;
00195             friend class const_iterator;
00196             friend class ParserContainer;
00197       };
00198 
00203       class const_iterator : public std::iterator<std::bidirectional_iterator_tag, T>
00204       {
00205          public:
00206             const_iterator(Parsers::const_iterator i,const ParserContainer* ref) : mIt(i),mRef(ref){}
00207             const_iterator(const const_iterator& orig) : mIt(orig.mIt), mRef(orig.mRef) {}
00208             const_iterator(const iterator& orig) : mIt(orig.mIt), mRef(orig.mRef) {}
00209             const_iterator() : mRef(0) {}
00210 
00211             const_iterator operator++() {const_iterator it(++mIt,mRef); return it;}
00212             const_iterator operator++(int) {const_iterator it(mIt++,mRef); return it;}
00213             const_iterator operator--() {const_iterator it(--mIt,mRef); return it;}
00214             const_iterator operator--(int) {const_iterator it(mIt--,mRef); return it;}
00215             bool operator!=(const const_iterator& rhs) { return mIt != rhs.mIt; }
00216             bool operator==(const const_iterator& rhs) { return mIt == rhs.mIt; }
00217             bool operator!=(const iterator& rhs) { return mIt != rhs.mIt; }
00218             bool operator==(const iterator& rhs) { return mIt == rhs.mIt; }
00219             const_iterator& operator=(const const_iterator& rhs) 
00220             {
00221                mIt = rhs.mIt;
00222                mRef = rhs.mRef;
00223                return *this;
00224             }
00225             const_iterator& operator=(const iterator& rhs) 
00226             {
00227                mIt = rhs.mIt; 
00228                mRef = rhs.mRef;
00229                return *this;
00230             }
00231             const T& operator*() {return ensureInitialized(*mIt,mRef);}
00232             const T* operator->() {return &ensureInitialized(*mIt,mRef);}
00233          private:
00234             friend class iterator;
00235             typename Parsers::const_iterator mIt;
00236             const ParserContainer* mRef;
00237       };
00238 
00242       iterator begin() { return iterator(mParsers.begin(),this); }
00243 
00247       iterator end() { return iterator(mParsers.end(),this); }
00248 
00253       iterator erase(iterator i)
00254       {
00255          freeParser(*i.mIt);
00256          return iterator(mParsers.erase(i.mIt),this);
00257       }
00258 
00262       bool find(const T& rhs) const
00263       {
00264          for (typename Parsers::const_iterator i = mParsers.begin();
00265               i != mParsers.end(); ++i)
00266          {
00267             // operator== defined by default, but often not usefully
00268             if (rhs.isEqual(ensureInitialized(*i,this)))
00269             {
00270                return true;
00271             }
00272          }
00273 
00274          return false;
00275       }
00276 
00281       virtual void parseAll()
00282       {
00283          for (typename Parsers::const_iterator i = mParsers.begin();
00284               i != mParsers.end(); ++i)
00285          {
00286             ensureInitialized(*i,this).checkParsed();
00287          }
00288       }
00289 
00294       const_iterator begin() const { return const_iterator(mParsers.begin(),this); }
00295 
00300       const_iterator end() const { return const_iterator(mParsers.end(),this); }
00301 
00305       virtual ParserContainerBase* clone() const
00306       {
00307          return new ParserContainer(*this);
00308       }
00309 
00310    private:
00311       friend class ParserContainer<T>::iterator;
00312       friend class ParserContainer<T>::const_iterator;
00313 
00317       static T& ensureInitialized(HeaderKit& kit, ParserContainer* ref)
00318       {
00319          if(!kit.pc)
00320          {
00321             if(ref)
00322             {
00323                PoolBase* pool(ref->mPool);
00324                kit.pc=new (pool) T(kit.hfv, ref->mType, pool);
00325             }
00326             else
00327             {
00328                kit.pc=new T(kit.hfv, Headers::NONE);
00329             }
00330          }
00331          return *static_cast<T*>(kit.pc);
00332       }
00333 
00334       static const T& ensureInitialized(const HeaderKit& kit, 
00335                                  const ParserContainer* ref)
00336       {
00337          if(!kit.pc)
00338          {
00339             HeaderKit& nc_kit(const_cast<HeaderKit&>(kit));
00340             if(ref)
00341             {
00342                ParserContainer* nc_ref(const_cast<ParserContainer*>(ref));
00343                PoolBase* pool(nc_ref->mPool);
00344                nc_kit.pc=new (pool) T(kit.hfv, ref->mType, pool);
00345             }
00346             else
00347             {
00348                nc_kit.pc=new T(kit.hfv, Headers::NONE);
00349             }
00350          }
00351          return *static_cast<T*>(kit.pc);
00352       }
00353 };
00354 
00355 template <class T>
00356 EncodeStream&
00357 insert(EncodeStream& s, const resip::ParserContainer<T>& c)
00358 {
00359    s << "[";
00360    for (typename resip::ParserContainer <T>::const_iterator i = c.begin();
00361         i != c.end(); i++) 
00362    {
00363       if (i != c.begin()) 
00364       {
00365          s << ", ";
00366       }
00367       // recurse
00368       insert(s, *i);
00369    }
00370    s << "]";
00371    return s;
00372 }
00373  
00374 }
00375 
00376 #endif
00377 
00378 /* ====================================================================
00379  * The Vovida Software License, Version 1.0 
00380  * 
00381  * Copyright (c) 2000-2005
00382  * 
00383  * Redistribution and use in source and binary forms, with or without
00384  * modification, are permitted provided that the following conditions
00385  * are met:
00386  * 
00387  * 1. Redistributions of source code must retain the above copyright
00388  *    notice, this list of conditions and the following disclaimer.
00389  * 
00390  * 2. Redistributions in binary form must reproduce the above copyright
00391  *    notice, this list of conditions and the following disclaimer in
00392  *    the documentation and/or other materials provided with the
00393  *    distribution.
00394  * 
00395  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00396  *    and "Vovida Open Communication Application Library (VOCAL)" must
00397  *    not be used to endorse or promote products derived from this
00398  *    software without prior written permission. For written
00399  *    permission, please contact vocal@vovida.org.
00400  *
00401  * 4. Products derived from this software may not be called "VOCAL", nor
00402  *    may "VOCAL" appear in their name, without prior written
00403  *    permission of Vovida Networks, Inc.
00404  * 
00405  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00406  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00407  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00408  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00409  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00410  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00411  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00412  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00413  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00414  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00415  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00416  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00417  * DAMAGE.
00418  * 
00419  * ====================================================================
00420  * 
00421  * This software consists of voluntary contributions made by Vovida
00422  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00423  * Inc.  For more information on Vovida Networks, Inc., please see
00424  * <http://www.vovida.org/>.
00425  *
00426  */