00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _IAIAUTOBUFFER_H_
00022 #define _IAIAUTOBUFFER_H_
00023
00024 #include "AITypes.h"
00025
00026 #include <string>
00027
00030 namespace ai {
00031
00034 class SPAlloc {
00035 public:
00040 static void* AllocateBlock(size_t byteCount);
00044 static void DeleteBlock(void* block);
00045 };
00046
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template<class elem, typename size_type=size_t, class A=SPAlloc> class AutoBuffer {
00064 public:
00065 typedef elem* iterator;
00066 typedef const elem* const_iterator;
00067
00071 explicit AutoBuffer (size_type count = 0)
00072 : fCapacity(count),
00073 fBuffer(0)
00074 {
00075 if ( fCapacity > 0 )
00076 {
00077 fBuffer = reinterpret_cast<elem*>(A::AllocateBlock(ByteCount(fCapacity)));
00078 Init();
00079 }
00080 }
00084 AutoBuffer (const AutoBuffer& b)
00085 : fCapacity(b.fCapacity),
00086 fBuffer(0)
00087 {
00088 if ( fCapacity > 0 )
00089 {
00090 fBuffer = reinterpret_cast<elem*>(A::AllocateBlock(ByteCount(fCapacity)));
00091 Copy(b.fBuffer);
00092 }
00093 }
00094
00095 #ifdef AI_HAS_RVALUE_REFERENCES
00096
00099 AutoBuffer (AutoBuffer&& b) AINOEXCEPT : fCapacity{b.fCapacity}, fBuffer{b.fBuffer}
00100 {
00101 b.fBuffer = nullptr;
00102 }
00103 #endif
00104
00107 ~AutoBuffer ()
00108 {
00109 if ( fBuffer )
00110 {
00111 Destroy(fBuffer);
00112 A::DeleteBlock(fBuffer);
00113 }
00114 }
00115
00119 bool IsValid () const
00120 {
00121 return fBuffer != 0;
00122 }
00123
00128 elem* GetBuffer () const
00129 {
00130 return fBuffer;
00131 }
00132
00133 explicit operator elem* () const
00134 {
00135 return GetBuffer();
00136 }
00137
00144 elem& operator[] (size_type n)
00145 {
00146 return fBuffer[n];
00147 }
00148
00149 const elem& operator[] (size_type n) const
00150 {
00151 return fBuffer[n];
00152 }
00153
00157 elem& front()
00158 {
00159 return fBuffer[0];
00160 }
00161
00162 const elem& front() const
00163 {
00164 return fBuffer[0];
00165 }
00166
00170 elem& back()
00171 {
00172 return fBuffer[fCapacity - 1];
00173 }
00174
00175 const elem& back() const
00176 {
00177 return fBuffer[fCapacity - 1];
00178 }
00179
00183 size_type GetCount () const AINOEXCEPT
00184 {
00185 return size();
00186 }
00187
00188 size_type size() const AINOEXCEPT
00189 {
00190 return fCapacity;
00191 }
00192
00193 bool empty() const AINOEXCEPT
00194 {
00195 return fCapacity == 0;
00196 }
00197
00198
00205 void Resize (size_type newSize)
00206 {
00207 if ( newSize != fCapacity )
00208 {
00209 elem *newBuffer = reinterpret_cast<elem*>(A::AllocateBlock(ByteCount(newSize)));
00210 if ( fBuffer )
00211 {
00212 elem* oldBuffer = fBuffer;
00213 fBuffer = newBuffer;
00214 Copy(oldBuffer, 0, fCapacity < newSize ? fCapacity : newSize );
00215
00216
00217 Init(fCapacity, newSize);
00218
00219 Destroy(oldBuffer, 0, fCapacity);
00220 A::DeleteBlock(oldBuffer);
00221 }
00222 else
00223 {
00224 fBuffer = newBuffer;
00225 Init();
00226 }
00227 fCapacity = newSize;
00228 }
00229 }
00230
00231 AutoBuffer& operator= (const AutoBuffer& rhs)
00232 {
00233 if ( this != &rhs )
00234 {
00235 if ( fCapacity != rhs.fCapacity )
00236 {
00237 Destroy(fBuffer);
00238 A::DeleteBlock(fBuffer);
00239 fBuffer = reinterpret_cast<elem*>(A::AllocateBlock(ByteCount(rhs.fCapacity)));
00240 fCapacity = rhs.fCapacity;
00241 }
00242 Copy(rhs.fBuffer);
00243 }
00244 return *this;
00245 }
00246
00247 #ifdef AI_HAS_RVALUE_REFERENCES
00248 AutoBuffer& operator= (AutoBuffer&& rhs) AINOEXCEPT
00249 {
00250 fCapacity = rhs.fCapacity;
00251 std::swap(fBuffer, rhs.fBuffer);
00252 return *this;
00253 }
00254 #endif
00255
00256 iterator begin() AINOEXCEPT { return fBuffer; }
00257 iterator end() AINOEXCEPT { return fBuffer + fCapacity; }
00258 const_iterator begin() const AINOEXCEPT { return fBuffer; }
00259 const_iterator end() const AINOEXCEPT { return fBuffer + fCapacity; }
00260
00261 static size_type lastIndex ()
00262 { return size_type(-1); }
00263 private:
00264 void Init (size_type start = 0, size_type end = lastIndex())
00265 {
00266 size_type elemCount = (end == lastIndex() ? GetCount() : end);
00267 for (size_type i = start; i < elemCount; ++i)
00268 {
00269
00270 new (&fBuffer[i])elem;
00271 }
00272 }
00273 void Destroy (elem* e, size_type start = 0, size_type end = lastIndex())
00274 {
00275 size_type elemCount = (end == lastIndex() ? GetCount() : end);
00276 for (size_type i = start; i < elemCount; ++i)
00277 {
00278 e[i].~elem();
00279 }
00280 }
00281 void Copy (const elem* e, size_type start = 0, size_type end = lastIndex())
00282 {
00283 size_type elemCount = (end == lastIndex() ? GetCount() : end);
00284 for (size_type i = start; i < elemCount; ++i)
00285 {
00286 fBuffer[i] = e[i];
00287 }
00288 }
00289 size_type ByteCount (size_type elemCount)
00290 {
00291 return elemCount * sizeof(elem);
00292 }
00293 private:
00294 size_type fCapacity;
00295 elem* fBuffer;
00296 };
00297
00298 }
00299
00300 #endif // _IAIAUTOBUFFER_H_