00001
00002
00003 #ifndef CRYPTOPP_SECBLOCK_H
00004 #define CRYPTOPP_SECBLOCK_H
00005
00006 #include "config.h"
00007 #include "misc.h"
00008 #include <string.h>
00009 #include <assert.h>
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013
00014
00015 template<class T>
00016 class AllocatorBase
00017 {
00018 public:
00019 typedef T value_type;
00020 typedef size_t size_type;
00021 #ifdef CRYPTOPP_MSVCRT6
00022 typedef ptrdiff_t difference_type;
00023 #else
00024 typedef std::ptrdiff_t difference_type;
00025 #endif
00026 typedef T * pointer;
00027 typedef const T * const_pointer;
00028 typedef T & reference;
00029 typedef const T & const_reference;
00030
00031 pointer address(reference r) const {return (&r);}
00032 const_pointer address(const_reference r) const {return (&r); }
00033 void construct(pointer p, const T& val) {new (p) T(val);}
00034 void destroy(pointer p) {p->~T();}
00035 size_type max_size() const {return ~size_type(0)/sizeof(T);}
00036
00037 protected:
00038 static void CheckSize(size_t n)
00039 {
00040 if (n > ~size_t(0) / sizeof(T))
00041 throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
00042 }
00043 };
00044
00045 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
00046 typedef typename AllocatorBase<T>::value_type value_type;\
00047 typedef typename AllocatorBase<T>::size_type size_type;\
00048 typedef typename AllocatorBase<T>::difference_type difference_type;\
00049 typedef typename AllocatorBase<T>::pointer pointer;\
00050 typedef typename AllocatorBase<T>::const_pointer const_pointer;\
00051 typedef typename AllocatorBase<T>::reference reference;\
00052 typedef typename AllocatorBase<T>::const_reference const_reference;
00053
00054 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00055
00056 #pragma warning(push)
00057 #pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning
00058 #endif
00059
00060 template <class T, class A>
00061 typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
00062 {
00063 if (oldSize == newSize)
00064 return p;
00065
00066 if (preserve)
00067 {
00068 A b;
00069 typename A::pointer newPointer = b.allocate(newSize, NULL);
00070 memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
00071 a.deallocate(p, oldSize);
00072 std::swap(a, b);
00073 return newPointer;
00074 }
00075 else
00076 {
00077 a.deallocate(p, oldSize);
00078 return a.allocate(newSize, NULL);
00079 }
00080 }
00081
00082 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00083 #pragma warning(pop)
00084 #endif
00085
00086 template <class T>
00087 class AllocatorWithCleanup : public AllocatorBase<T>
00088 {
00089 public:
00090 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00091
00092 pointer allocate(size_type n, const void * = NULL)
00093 {
00094 CheckSize(n);
00095 if (n == 0)
00096 return NULL;
00097 return new T[n];
00098 }
00099
00100 void deallocate(void *p, size_type n)
00101 {
00102 memset(p, 0, n*sizeof(T));
00103 delete [] (T *)p;
00104 }
00105
00106 pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
00107 {
00108 return StandardReallocate(*this, p, oldSize, newSize, preserve);
00109 }
00110
00111
00112
00113 template <class U> struct rebind { typedef AllocatorWithCleanup<U> other; };
00114 };
00115
00116 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
00117 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
00118 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
00119
00120 template <class T>
00121 class NullAllocator : public AllocatorBase<T>
00122 {
00123 public:
00124 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00125
00126 pointer allocate(size_type n, const void * = NULL)
00127 {
00128 assert(false);
00129 return NULL;
00130 }
00131
00132 void deallocate(void *p, size_type n)
00133 {
00134 assert(false);
00135 }
00136
00137 size_type max_size() const {return 0;}
00138 };
00139
00140
00141
00142
00143 template <class T, size_t S, class A = NullAllocator<T> >
00144 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
00145 {
00146 public:
00147 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00148
00149 FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
00150
00151 pointer allocate(size_type n)
00152 {
00153 if (n <= S && !m_allocated)
00154 {
00155 m_allocated = true;
00156 return m_array;
00157 }
00158 else
00159 return m_fallbackAllocator.allocate(n);
00160 }
00161
00162 pointer allocate(size_type n, const void *hint)
00163 {
00164 if (n <= S && !m_allocated)
00165 {
00166 m_allocated = true;
00167 return m_array;
00168 }
00169 else
00170 return m_fallbackAllocator.allocate(n, hint);
00171 }
00172
00173 void deallocate(void *p, size_type n)
00174 {
00175 if (p == m_array)
00176 {
00177 assert(n <= S);
00178 assert(m_allocated);
00179 m_allocated = false;
00180 memset(p, 0, n*sizeof(T));
00181 }
00182 else
00183 m_fallbackAllocator.deallocate(p, n);
00184 }
00185
00186 pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
00187 {
00188 if (p == m_array && newSize <= S)
00189 {
00190 assert(oldSize <= S);
00191 if (oldSize > newSize)
00192 memset(p + newSize, 0, (oldSize-newSize)*sizeof(T));
00193 return p;
00194 }
00195
00196 pointer newPointer = allocate(newSize, NULL);
00197 if (preserve)
00198 memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
00199 deallocate(p, oldSize);
00200 return newPointer;
00201 }
00202
00203 size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
00204
00205 private:
00206 T m_array[S];
00207 A m_fallbackAllocator;
00208 bool m_allocated;
00209 };
00210
00211
00212 template <class T, class A = AllocatorWithCleanup<T> >
00213 class SecBlock
00214 {
00215 public:
00216 typedef typename A::value_type value_type;
00217 typedef typename A::pointer iterator;
00218 typedef typename A::const_pointer const_iterator;
00219 typedef typename A::size_type size_type;
00220
00221 explicit SecBlock(size_type size=0)
00222 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
00223 SecBlock(const SecBlock<T, A> &t)
00224 : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
00225 SecBlock(const T *t, size_type len)
00226 : m_size(len)
00227 {
00228 m_ptr = m_alloc.allocate(len, NULL);
00229 if (t == NULL)
00230 memset(m_ptr, 0, len*sizeof(T));
00231 else
00232 memcpy(m_ptr, t, len*sizeof(T));
00233 }
00234
00235 ~SecBlock()
00236 {m_alloc.deallocate(m_ptr, m_size);}
00237
00238 operator const void *() const
00239 {return m_ptr;}
00240 operator void *()
00241 {return m_ptr;}
00242 #if defined(__GNUC__) && __GNUC__ < 3 // reduce warnings
00243 operator const void *()
00244 {return m_ptr;}
00245 #endif
00246
00247 operator const T *() const
00248 {return m_ptr;}
00249 operator T *()
00250 {return m_ptr;}
00251 #if defined(__GNUC__) && __GNUC__ < 3 // reduce warnings
00252 operator const T *()
00253 {return m_ptr;}
00254 #endif
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 iterator begin()
00269 {return m_ptr;}
00270 const_iterator begin() const
00271 {return m_ptr;}
00272 iterator end()
00273 {return m_ptr+m_size;}
00274 const_iterator end() const
00275 {return m_ptr+m_size;}
00276
00277 typename A::pointer data() {return m_ptr;}
00278 typename A::const_pointer data() const {return m_ptr;}
00279
00280 size_type size() const {return m_size;}
00281 bool empty() const {return m_size == 0;}
00282
00283 size_type SizeInBytes() const {return m_size*sizeof(T);}
00284
00285 void Assign(const T *t, size_type len)
00286 {
00287 New(len);
00288 memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
00289 }
00290
00291 void Assign(const SecBlock<T, A> &t)
00292 {
00293 New(t.m_size);
00294 memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
00295 }
00296
00297 SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
00298 {
00299 Assign(t);
00300 return *this;
00301 }
00302
00303 SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
00304 {
00305 size_type oldSize = m_size;
00306 Grow(m_size+t.m_size);
00307 memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
00308 return *this;
00309 }
00310
00311 SecBlock<T, A> operator+(const SecBlock<T, A> &t)
00312 {
00313 SecBlock<T, A> result(m_size+t.m_size);
00314 memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
00315 memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
00316 return result;
00317 }
00318
00319 bool operator==(const SecBlock<T, A> &t) const
00320 {
00321 return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
00322 }
00323
00324 bool operator!=(const SecBlock<T, A> &t) const
00325 {
00326 return !operator==(t);
00327 }
00328
00329 void New(size_type newSize)
00330 {
00331 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
00332 m_size = newSize;
00333 }
00334
00335 void CleanNew(size_type newSize)
00336 {
00337 New(newSize);
00338 memset(m_ptr, 0, m_size*sizeof(T));
00339 }
00340
00341 void Grow(size_type newSize)
00342 {
00343 if (newSize > m_size)
00344 {
00345 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00346 m_size = newSize;
00347 }
00348 }
00349
00350 void CleanGrow(size_type newSize)
00351 {
00352 if (newSize > m_size)
00353 {
00354 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00355 memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
00356 m_size = newSize;
00357 }
00358 }
00359
00360 void resize(size_type newSize)
00361 {
00362 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00363 m_size = newSize;
00364 }
00365
00366 void swap(SecBlock<T, A> &b)
00367 {
00368 std::swap(m_alloc, b.m_alloc);
00369 std::swap(m_size, b.m_size);
00370 std::swap(m_ptr, b.m_ptr);
00371 }
00372
00373
00374 A m_alloc;
00375 size_type m_size;
00376 T *m_ptr;
00377 };
00378
00379 typedef SecBlock<byte> SecByteBlock;
00380 typedef SecBlock<word> SecWordBlock;
00381
00382 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
00383 class FixedSizeSecBlock : public SecBlock<T, A>
00384 {
00385 public:
00386 explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
00387 };
00388
00389 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
00390 class SecBlockWithHint : public SecBlock<T, A>
00391 {
00392 public:
00393 explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
00394 };
00395
00396 template<class T, class U>
00397 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
00398 template<class T, class U>
00399 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
00400
00401 NAMESPACE_END
00402
00403 NAMESPACE_BEGIN(std)
00404 template <class T, class A>
00405 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
00406 {
00407 a.swap(b);
00408 }
00409
00410 #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
00411 template <class _Tp1, class _Tp2>
00412 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
00413 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
00414 {
00415 return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
00416 }
00417 #endif
00418
00419 NAMESPACE_END
00420
00421 #endif