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