/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. This program 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; version 2 of the License. This program 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* block.hpp provides word and byte blocks with configurable allocators */ #ifndef TAO_CRYPT_BLOCK_HPP #define TAO_CRYPT_BLOCK_HPP #include "misc.hpp" #include // memcpy #include // ptrdiff_t #ifdef USE_SYS_STL #include #else #include "algorithm.hpp" #endif namespace STL = STL_NAMESPACE; 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: }; // 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); STL::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) { if (n > this->max_size()) return 0; if (n == 0) return 0; return NEW_TC T[n]; } void deallocate(void* p, size_type n) { memset(p, 0, n * sizeof(T)); tcArrayDelete((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) { return buffer_[i]; } const T& operator[] (word32 i) const { 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) { STL::swap(sz_, other.sz_); STL::swap(buffer_, other.buffer_); STL::swap(allocator_, other.allocator_); } ~Block() { allocator_.deallocate(buffer_, sz_); } private: A allocator_; word32 sz_; // size in Ts T* buffer_; }; typedef Block ByteBlock; typedef Block WordBlock; typedef Block Word32Block; } // namespace #endif // TAO_CRYPT_BLOCK_HPP