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