|
NCBI C++ ToolKit
|
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
1.7.5.1
Modified on Wed May 23 12:57:06 2012 by modify_doxy.py rev. 337098