NCBI C++ ToolKit
simple_buffer.hpp
Go to the documentation of this file.
00001 #ifndef UTIL_SIMPLE_BUFFER__HPP
00002 #define UTIL_SIMPLE_BUFFER__HPP
00003 
00004 /*  $Id: simple_buffer.hpp 45898 2010-05-27 14:41:33Z satskyse $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Authors:  Anatoliy Kuznetsov
00030  *
00031  * File Description: Simple (fast) resizable buffer
00032  *
00033  */
00034 
00035 #include <corelib/ncbistd.hpp>
00036 
00037 BEGIN_NCBI_SCOPE
00038 
00039 
00040 class CSimpleResizeStrategy
00041 {
00042 public:
00043     static size_t GetNewCapacity(size_t /*cur_capacity*/,
00044                                  size_t requested_size)
00045     { return requested_size; }
00046 };
00047 
00048 class CAgressiveResizeStrategy
00049 {
00050 public:
00051     static size_t GetNewCapacity(size_t /*cur_capacity*/,
00052                                  size_t requested_size)
00053     {
00054         size_t  new_size = requested_size + requested_size / 2;
00055 
00056         // Overrun
00057         if (new_size < requested_size)
00058             return std::numeric_limits<size_t>::max();
00059         return new_size;
00060     }
00061 };
00062 
00063 class CPowerOfTwoResizeStrategy
00064 {
00065 public:
00066     static size_t GetNewCapacity(size_t /*cur_capacity*/,
00067                                  size_t required_size)
00068     {
00069         size_t  new_size = required_size * 2;
00070 
00071         // Overrun
00072         if (new_size < required_size)
00073             return std::numeric_limits<size_t>::max();
00074         return new_size;
00075     }
00076 };
00077 
00078 /// Reallocable memory buffer (no memory copy overhead)
00079 /// Mimics vector<>, without the overhead of explicit initialization of all
00080 /// items
00081 ///
00082 
00083 template <typename T = unsigned char,
00084           typename ResizeStrategy = CPowerOfTwoResizeStrategy>
00085 class CSimpleBufferT
00086 {
00087 public:
00088     typedef T             value_type;
00089     typedef size_t        size_type;
00090 public:
00091     explicit CSimpleBufferT(size_type size=0)
00092     {
00093         if (size) {
00094             m_Buffer = x_Allocate(size);
00095         } else {
00096             m_Buffer = 0;
00097         }
00098         m_Size = m_Capacity = size;
00099     }
00100     ~CSimpleBufferT()
00101     {
00102         x_Deallocate();
00103     }
00104 
00105     CSimpleBufferT(const CSimpleBufferT& sb)
00106     {
00107         size_type new_size = sb.capacity();
00108         m_Buffer = x_Allocate(new_size);
00109         m_Capacity = new_size;
00110         m_Size = sb.size();
00111         memcpy(m_Buffer, sb.data(), m_Size*sizeof(value_type));
00112     }
00113 
00114     CSimpleBufferT& operator=(const CSimpleBufferT& sb)
00115     {
00116         if (this != &sb) {
00117             if (sb.size() <= m_Capacity) {
00118                 if (sb.size() < m_Size) {
00119                     x_Fill(m_Buffer + sb.size(), 0xcd, m_Capacity - sb.size());
00120                 }
00121                 m_Size = sb.size();
00122             } else {
00123                 x_Deallocate();
00124                 m_Buffer = x_Allocate(sb.capacity());
00125                 m_Capacity = sb.capacity();
00126                 m_Size = sb.size();
00127             }
00128             memcpy(m_Buffer, sb.data(), m_Size*sizeof(value_type));
00129         }
00130         return *this;
00131     }
00132 
00133     CSimpleBufferT& append(const void* buf, size_t len)
00134     {
00135         size_t offs = m_Size;
00136 
00137         resize( m_Size + len );
00138         memcpy( m_Buffer + offs, buf, len );
00139         return *this;
00140     }
00141 
00142     size_type size() const { return m_Size; }
00143     size_type capacity() const { return m_Capacity; }
00144 
00145     void reserve(size_type new_size)
00146     {
00147         if (new_size > m_Capacity) {
00148             value_type* new_buffer = x_Allocate(new_size);
00149             if (m_Size) {
00150                 memcpy(new_buffer, m_Buffer, m_Size*sizeof(value_type));
00151             }
00152             x_Deallocate();
00153             m_Buffer = new_buffer;
00154             m_Capacity = new_size;
00155         }
00156     }
00157 
00158     void resize(size_type new_size)
00159     {
00160         _ASSERT(m_Size <= m_Capacity);
00161         if (new_size <= m_Capacity) {
00162             if (new_size < m_Size) {
00163                 x_Fill(m_Buffer + new_size, 0xcd, m_Capacity - new_size);
00164             }
00165             m_Size = new_size;
00166         } else {
00167             size_t new_capacity =
00168                 ResizeStrategy::GetNewCapacity(m_Capacity,new_size);
00169             value_type* new_buffer = x_Allocate(new_capacity);
00170             if (m_Size) {
00171                 memcpy(new_buffer, m_Buffer, m_Size*sizeof(value_type));
00172             }
00173             x_Deallocate();
00174             m_Buffer = new_buffer;
00175             m_Capacity = new_capacity;
00176             m_Size = new_size;
00177         }
00178     }
00179 
00180     /// Resize the buffer. No data preservation.
00181     void resize_mem(size_type new_size)
00182     {
00183         if (new_size <= m_Capacity) {
00184             if (new_size < m_Size) {
00185                 x_Fill(m_Buffer + new_size, 0xcd, m_Capacity - new_size);
00186             }
00187             m_Size = new_size;
00188         } else {
00189             x_Deallocate();
00190             size_t new_capacity = ResizeStrategy::GetNewCapacity(m_Capacity,new_size);
00191             m_Buffer = x_Allocate(new_capacity);
00192             m_Capacity = new_capacity;
00193             m_Size = new_size;
00194         }
00195     }
00196 
00197     void swap(CSimpleBufferT<T>& other)
00198     {
00199         swap(m_Buffer, other.m_Buffer);
00200         swap(m_Size, other.m_Size);
00201         swap(m_Capacity, other.m_Capacity);
00202     }
00203 
00204     /// Reserve memory. No data preservation guarantees.
00205     void reserve_mem(size_type new_size)
00206     {
00207         if (new_size > m_Capacity) {
00208             x_Deallocate();
00209             m_Buffer = x_Allocate(new_size);
00210             m_Capacity = new_size;
00211             x_Fill(m_Buffer, 0xcd, m_Capacity);
00212         }
00213     }
00214 
00215     void clear()
00216     {
00217         resize(0);
00218     }
00219 
00220     const value_type& operator[](size_type i) const
00221     {
00222         _ASSERT(m_Buffer);
00223         _ASSERT(i < m_Size);
00224         return m_Buffer[i];
00225     }
00226     value_type& operator[](size_type i)
00227     {
00228         _ASSERT(m_Buffer);
00229         _ASSERT(i < m_Size);
00230         return m_Buffer[i];
00231     }
00232 
00233     const value_type* data() const
00234     {
00235         return m_Buffer;
00236     }
00237     value_type* data()
00238     {
00239         return m_Buffer;
00240     }
00241 
00242 
00243 
00244 private:
00245     void x_Fill(value_type* buffer, int value, size_t elem)
00246     {
00247 #ifdef _DEBUG
00248         memset(buffer, value, elem * sizeof(value_type));
00249 #endif
00250     }
00251 
00252     void x_Deallocate()
00253     {
00254         if (m_Buffer) {
00255             x_Fill(m_Buffer, 0xfd, m_Capacity);
00256             delete [] m_Buffer;
00257         }
00258         m_Buffer = NULL;
00259         m_Size = m_Capacity = 0;
00260     }
00261 
00262     value_type* x_Allocate(size_t elem)
00263     {
00264         value_type* buf = new value_type[elem];
00265         x_Fill(buf, 0xcd, elem);
00266         return buf;
00267     }
00268 
00269 private:
00270     value_type* m_Buffer;
00271     size_type   m_Size;
00272     size_type   m_Capacity;
00273 };
00274 
00275 typedef CSimpleBufferT<> CSimpleBuffer;
00276 
00277 END_NCBI_SCOPE
00278 
00279 #endif
Modified on Wed May 23 12:57:06 2012 by modify_doxy.py rev. 337098