/* block.hpp * * Copyright (C) 2003 Sawtooth Consulting Ltd. * * This file is part of yaSSL. * * yaSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* block.hpp provides word and byte blocks with configurable allocators */ #ifndef TAO_CRYPT_BLOCK_HPP #define TAO_CRYPT_BLOCK_HPP #include "algorithm.hpp" // mySTL::swap #include "stdexcept.hpp" // mySTL::runtime_error #include "misc.hpp" #include // memcpy #include // ptrdiff_t #if defined(_MSC_VER) && defined(_CRTAPI1) #define TAOCRYPT_MSVCRT6 #endif namespace TaoCrypt { // a Base class for Allocators template class AllocatorBase { public: typedef T value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; pointer address(reference r) const {return (&r);} const_pointer address(const_reference r) const {return (&r); } void construct(pointer p, const T& val) {new (p) T(val);} void destroy(pointer p) {p->~T();} size_type max_size() const {return ~size_type(0)/sizeof(T);} protected: static void CheckSize(size_t n) { assert(n <= ~size_t(0) / sizeof(T)); } }; // General purpose realloc template typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) { if (oldSize == newSize) return p; if (preserve) { A b = A(); typename A::pointer newPointer = b.allocate(newSize, 0); memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize)); a.deallocate(p, oldSize); mySTL::swap(a, b); return newPointer; } else { a.deallocate(p, oldSize); return a.allocate(newSize, 0); } } // Allocator that zeros out memory on deletion template class AllocatorWithCleanup : public AllocatorBase { public: typedef typename AllocatorBase::pointer pointer; typedef typename AllocatorBase::size_type size_type; pointer allocate(size_type n, const void* = 0) { CheckSize(n); if (n == 0) return 0; return new (tc) T[n]; } void deallocate(void* p, size_type n) { memset(p, 0, n * sizeof(T)); delete [] (T*)p; } pointer reallocate(T* p, size_type oldSize, size_type newSize, bool preserve) { return StdReallocate(*this, p, oldSize, newSize, preserve); } // VS.NET STL enforces the policy of "All STL-compliant allocators have to // provide a template class member called rebind". template struct rebind { typedef AllocatorWithCleanup other;}; }; // Block class template template > class Block { public: explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_)) { CleanNew(sz_); } Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_)) { memcpy(buffer_, buff, sz_ * sizeof(T)); } Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_)) { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); } Block& operator=(const Block& that) { Block tmp(that); Swap(tmp); return *this; } T& operator[] (word32 i) { assert(i < sz_); return buffer_[i]; } const T& operator[] (word32 i) const { assert(i < sz_); return buffer_[i]; } T* operator+ (word32 i) { return buffer_ + i; } const T* operator+ (word32 i) const { return buffer_ + i; } word32 size() const { return sz_; } T* get_buffer() const { return buffer_; } T* begin() const { return get_buffer(); } void CleanGrow(word32 newSize) { if (newSize > sz_) { buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true); memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T)); sz_ = newSize; } } void CleanNew(word32 newSize) { New(newSize); memset(buffer_, 0, sz_ * sizeof(T)); } void New(word32 newSize) { buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false); sz_ = newSize; } void resize(word32 newSize) { buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true); sz_ = newSize; } void Swap(Block& other) { mySTL::swap(sz_, other.sz_); mySTL::swap(buffer_, other.buffer_); mySTL::swap(allocator_, other.allocator_); } ~Block() { allocator_.deallocate(buffer_, sz_); } private: word32 sz_; // size in Ts T* buffer_; A allocator_; }; typedef Block ByteBlock; typedef Block WordBlock; typedef Block Word32Block; } // namespace #endif // TAO_CRYPT_BLOCK_HPP