00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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
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 } }
00371 #endif
00372
00373 #endif // _SUPPORT_BUFFER_CHAIN_H_
00374