BufferChain.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 Palmsource, Inc.
00003  * 
00004  * This software is licensed as described in the file LICENSE, which
00005  * you should have received as part of this distribution. The terms
00006  * are also available at http://www.openbinder.org/license.html.
00007  * 
00008  * This software consists of voluntary contributions made by many
00009  * individuals. For the exact contribution history, see the revision
00010  * history and logs, available at http://www.openbinder.org
00011  */
00012 
00013 #ifndef _SUPPORT_BUFFER_CHAIN_H_
00014 #define _SUPPORT_BUFFER_CHAIN_H_
00015 
00016 #include <support/Buffer.h>
00017 #include <support/StdIO.h>
00018 
00019 #include <string.h>
00020 
00021 #if _SUPPORTS_NAMESPACE
00022 namespace palmos {
00023 namespace support {
00024 #endif
00025 
00026 template<class BUFFERTYPE>
00027 class SBufferChain
00028 {
00029     public:
00030         inline              SBufferChain();
00031         inline              SBufferChain(const SBufferChain<BUFFERTYPE>& chain);
00032         inline              SBufferChain(const BUFFERTYPE& chain);
00033         inline              ~SBufferChain();
00034 
00035         inline  SBufferChain<BUFFERTYPE>& operator=(const SBufferChain<BUFFERTYPE>& chain);
00036         inline  SBufferChain<BUFFERTYPE>& operator=(const BUFFERTYPE& chain);
00037 
00038         inline  void        MakeEmpty();
00039         
00040         inline  status_t    AppendBuffer(const BUFFERTYPE& buffer);
00041         inline  status_t    PrependBuffer(const BUFFERTYPE& buffer);
00042         
00043         inline  status_t    AppendChain(const SBufferChain<BUFFERTYPE>& chain);
00044         inline  status_t    AppendChain(const BUFFERTYPE& buffer);
00045         inline  status_t    PrependChain(const SBufferChain<BUFFERTYPE>& chain);
00046         inline  status_t    PrependChain(const BUFFERTYPE& buffer);
00047         
00048         inline  status_t    RemoveFirst();
00049 
00050         inline  size_t      Size() const;
00051 
00052         BUFFERTYPE *        RootBuffer() const;     
00053 
00054     private:
00055         enum
00056         {
00057             ALLOC_SIZE      = 4
00058         };
00059         
00060         BUFFERTYPE *        m_root;
00061         BUFFERTYPE *        m_last;
00062         BUFFERTYPE *        m_free;
00063 
00064         BUFFERTYPE *        next();
00065         status_t            alloc(size_t capacity);
00066 //      static status_t     copy(const BUFFERTYPE * from, BUFFERTYPE ** root, BUFFERTYPE ** last);
00067         status_t            init_copy(const BUFFERTYPE* clone);
00068         void                free_chain(BUFFERTYPE* root);
00069 };
00070 
00071 template<class BUFFERTYPE> inline BUFFERTYPE *
00072 SBufferChain<BUFFERTYPE>::next()
00073 {
00074     if (!m_free)
00075     {
00076         status_t err = alloc(ALLOC_SIZE);
00077         if (err < B_OK) return 0;
00078     }
00079 
00080     BUFFERTYPE * result = m_free;
00081     m_free = static_cast<BUFFERTYPE*>(m_free->next);
00082     result->next = 0;
00083     return result;
00084 }
00085 
00086 template<class BUFFERTYPE> inline status_t
00087 SBufferChain<BUFFERTYPE>::alloc(size_t capacity)
00088 {
00089     if (m_free != 0) return B_NOT_ALLOWED;
00090 
00091     BUFFERTYPE * result = 0;
00092     BUFFERTYPE ** i = &result;
00093     for (size_t n = 0; n < capacity; n++)
00094     {
00095         BUFFERTYPE * b = new BUFFERTYPE();
00096         if (!b) return B_NO_MEMORY;
00097         *i = b;
00098         i = (BUFFERTYPE**)(&b->next);
00099     }
00100     *i = 0;
00101 
00102     m_free = result;
00103 
00104     return B_OK;
00105 }
00106 
00107 #if 0
00108 template<class BUFFERTYPE> inline status_t
00109 SBufferChain<BUFFERTYPE>::copy(const BUFFERTYPE * from, BUFFERTYPE ** root, BUFFERTYPE ** last)
00110 {
00111     BUFFERTYPE ** i = root;
00112     for (const BUFFERTYPE * pos = from; pos; pos = static_cast<const BUFFERTYPE*>(pos->next))
00113     {
00114         if (m_free)
00115         {
00116             *i = m_free;
00117             m_free = m_free->next;
00118         }
00119         else
00120         {
00121             *i = new BUFFERTYPE(*pos);
00122             if (*i == 0) return B_NO_MEMORY;
00123         }
00124         *last = *i;
00125         i = (BUFFERTYPE**)(&(*i)->next);
00126     }
00127     *i = 0;
00128     return B_OK;
00129 }
00130 #endif
00131 
00132 template<class BUFFERTYPE> inline void
00133 SBufferChain<BUFFERTYPE>::free_chain(BUFFERTYPE* root)
00134 {
00135     for (BUFFERTYPE * i = root; i;)
00136     {
00137         BUFFERTYPE * next = static_cast<BUFFERTYPE*>(i->next);
00138         delete i;
00139         i = next;
00140     }
00141 }
00142 
00143 template<class BUFFERTYPE> inline
00144 SBufferChain<BUFFERTYPE>::SBufferChain()
00145 {
00146     m_root = 0;
00147     m_last = 0;
00148     m_free = 0;
00149 }
00150 
00151 template<class BUFFERTYPE> inline status_t
00152 SBufferChain<BUFFERTYPE>::init_copy(const BUFFERTYPE* clone)
00153 {
00154     m_last = 0;
00155     m_free = 0;
00156     m_root = 0;
00157     
00158     if (clone != 0)
00159     {
00160         return AppendChain(*clone);
00161     }
00162     return B_OK;
00163 }
00164 
00165 template<class BUFFERTYPE> inline
00166 SBufferChain<BUFFERTYPE>::SBufferChain(const BUFFERTYPE& chain)
00167 {
00168     init_copy(&chain);
00169 }
00170 
00171 template<class BUFFERTYPE> inline
00172 SBufferChain<BUFFERTYPE>::SBufferChain(const SBufferChain<BUFFERTYPE>& chain)
00173 {
00174     init_copy(chain.m_root);
00175 }
00176 
00177 template<class BUFFERTYPE> inline SBufferChain<BUFFERTYPE>&
00178 SBufferChain<BUFFERTYPE>::operator=(const SBufferChain<BUFFERTYPE>& chain)
00179 {
00180     MakeEmpty();
00181     AppendChain(chain);
00182     return *this;
00183 }
00184 
00185 template<class BUFFERTYPE> inline SBufferChain<BUFFERTYPE>&
00186 SBufferChain<BUFFERTYPE>::operator=(const BUFFERTYPE& chain)
00187 {
00188     MakeEmpty();
00189     AppendChain(chain);
00190     return *this;
00191 }
00192 
00193 template<class BUFFERTYPE> inline
00194 SBufferChain<BUFFERTYPE>::~SBufferChain()
00195 {
00196     free_chain(m_root);
00197     free_chain(m_free);
00198 }
00199 
00200 template<class BUFFERTYPE> inline void
00201 SBufferChain<BUFFERTYPE>::MakeEmpty()
00202 {
00203     if (m_last)
00204     {
00205         // move all entries to free list
00206         m_last->next = m_free;
00207         m_free = m_root;
00208         
00209         m_root = 0;
00210         m_last = 0;
00211     }
00212 }
00213 
00214 template<class BUFFERTYPE> inline status_t
00215 SBufferChain<BUFFERTYPE>::AppendBuffer(const BUFFERTYPE& buffer)
00216 {
00217     BUFFERTYPE * b = next();
00218     if (b == 0) return B_NO_MEMORY;
00219     *b = buffer;
00220     
00221     if (m_last == 0)
00222     {
00223         m_root = b;
00224         m_last = b;
00225     }
00226     else
00227     {
00228         m_last->next = b;
00229         m_last = b;
00230     }
00231     
00232     return B_OK;
00233 }
00234 
00235 template<class BUFFERTYPE> inline status_t
00236 SBufferChain<BUFFERTYPE>::PrependBuffer(const BUFFERTYPE& buffer)
00237 {
00238     BUFFERTYPE * b = next();
00239     if (b == 0) return B_NO_MEMORY;
00240     *b = buffer;
00241     
00242     if (m_root == 0)
00243     {
00244         m_root = b;
00245         m_last = b;
00246         b->next = 0;
00247     }
00248     else
00249     {
00250         b->next = m_root;
00251         m_root = b;
00252     }
00253 
00254     return B_OK;
00255 }
00256 
00257 template<class BUFFERTYPE> inline status_t
00258 SBufferChain<BUFFERTYPE>::AppendChain(const SBufferChain<BUFFERTYPE>& chain)
00259 {
00260     if (chain.m_root != 0)
00261     {
00262         return AppendChain(*chain.m_root);
00263     }
00264     return B_OK;
00265 }
00266 
00267 template<class BUFFERTYPE> inline status_t
00268 SBufferChain<BUFFERTYPE>::AppendChain(const BUFFERTYPE& buffer)
00269 {
00270     const BUFFERTYPE * src = &buffer;
00271     while (src != 0)
00272     {
00273         BUFFERTYPE * b = next();
00274         if (b == 0) return B_NO_MEMORY;
00275         *b = *src;
00276 
00277         if (m_last == 0)
00278         {
00279             m_root = b;
00280             m_last = b;
00281         }
00282         else
00283         {
00284             m_last->next = b;
00285             m_last = b;
00286         }
00287         
00288         src = static_cast<const BUFFERTYPE*>(src->next);
00289     }
00290     return B_OK;
00291 }
00292 
00293 template<class BUFFERTYPE> inline status_t
00294 SBufferChain<BUFFERTYPE>::PrependChain(const SBufferChain<BUFFERTYPE>& chain)
00295 {
00296     if (chain.m_root != 0)
00297     {
00298         return PrependChain(*chain.m_root);
00299     }
00300     return B_OK;
00301 }
00302 
00303 template<class BUFFERTYPE> inline status_t
00304 SBufferChain<BUFFERTYPE>::PrependChain(const BUFFERTYPE& buffer)
00305 {
00306     const BUFFERTYPE * src = &buffer;
00307     while (src != 0)
00308     {
00309         BUFFERTYPE * b = next();
00310         if (b == 0) return B_NO_MEMORY;
00311         *b = *src;
00312 
00313         if (m_root == 0)
00314         {
00315             m_root = b;
00316             m_last = b;
00317             b->next = 0;
00318         }
00319         else
00320         {
00321             b->next = m_root;
00322             m_root = b;
00323         }
00324         
00325         src = static_cast<const BUFFERTYPE*>(src->next);
00326     }
00327     return B_OK;
00328 }
00329 
00330 template<class BUFFERTYPE> inline status_t
00331 SBufferChain<BUFFERTYPE>::RemoveFirst()
00332 {
00333     if (m_root == 0)
00334     {
00335         return B_NOT_ALLOWED;
00336     }
00337 
00338     BUFFERTYPE * newRoot = static_cast<BUFFERTYPE*>(m_root->next);
00339     m_root->next = m_free;
00340     m_free = m_root;
00341     if (m_last == m_root)
00342     {
00343         m_last = 0;
00344     }
00345     m_root = newRoot;
00346 
00347     return B_OK;
00348 }
00349 
00350 template<class BUFFERTYPE> inline BUFFERTYPE *
00351 SBufferChain<BUFFERTYPE>::RootBuffer() const
00352 {
00353     return m_root;
00354 }
00355 
00356 template<class BUFFERTYPE> inline size_t
00357 SBufferChain<BUFFERTYPE>::Size() const
00358 {
00359     if (m_root)
00360     {
00361         return m_root->ChainSize();
00362     }
00363     else
00364     {
00365         return 0;
00366     }
00367 }
00368 
00369 #if _SUPPORTS_NAMESPACE
00370 } } // palmos::support
00371 #endif
00372 
00373 #endif // _SUPPORT_BUFFER_CHAIN_H_
00374