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