1 /*
2    Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; see the file COPYING. If not, write to the
15    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16    MA  02110-1335  USA.
17 */
18 
19 
20 /* block.hpp provides word and byte blocks with configurable allocators
21 */
22 
23 
24 #ifndef TAO_CRYPT_BLOCK_HPP
25 #define TAO_CRYPT_BLOCK_HPP
26 
27 #include "misc.hpp"
28 #include <string.h>         // memcpy
29 #include <stddef.h>         // ptrdiff_t
30 
31 #ifdef USE_SYS_STL
32     #include <algorithm>
33 #else
34     #include "algorithm.hpp"
35 #endif
36 
37 
38 namespace STL = STL_NAMESPACE;
39 
40 
41 namespace TaoCrypt {
42 
43 
44 // a Base class for Allocators
45 template<class T>
46 class AllocatorBase
47 {
48 public:
49     typedef T         value_type;
50     typedef size_t    size_type;
51     typedef ptrdiff_t difference_type;
52     typedef T*        pointer;
53     typedef const T*  const_pointer;
54     typedef T&        reference;
55     typedef const T&  const_reference;
56 
address(reference r) const57     pointer       address(reference r) const {return (&r);}
address(const_reference r) const58     const_pointer address(const_reference r) const {return (&r); }
construct(pointer p,const T & val)59     void          construct(pointer p, const T& val) {new (p) T(val);}
destroy(pointer p)60     void          destroy(pointer p) {p->~T();}
max_size() const61     size_type     max_size() const {return ~size_type(0)/sizeof(T);}
62 protected:
63 };
64 
65 
66 // General purpose realloc
67 template<typename T, class A>
StdReallocate(A & a,T * p,typename A::size_type oldSize,typename A::size_type newSize,bool preserve)68 typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize,
69                                   typename A::size_type newSize, bool preserve)
70 {
71     if (oldSize == newSize)
72         return p;
73 
74     if (preserve) {
75         A b = A();
76         typename A::pointer newPointer = b.allocate(newSize, 0);
77         memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize));
78         a.deallocate(p, oldSize);
79         STL::swap(a, b);
80         return newPointer;
81     }
82     else {
83         a.deallocate(p, oldSize);
84         return a.allocate(newSize, 0);
85     }
86 }
87 
88 
89 // Allocator that zeros out memory on deletion
90 template <class T>
91 class AllocatorWithCleanup : public AllocatorBase<T>
92 {
93 public:
94     typedef typename AllocatorBase<T>::pointer   pointer;
95     typedef typename AllocatorBase<T>::size_type size_type;
96 
allocate(size_type n,const void * =0)97     pointer allocate(size_type n, const void* = 0)
98     {
99         if (n > this->max_size())
100             return 0;
101         if (n == 0)
102             return 0;
103         return NEW_TC T[n];
104     }
105 
deallocate(void * p,size_type n)106     void deallocate(void* p, size_type n)
107     {
108         memset(p, 0, n * sizeof(T));
109         tcArrayDelete((T*)p);
110     }
111 
reallocate(T * p,size_type oldSize,size_type newSize,bool preserve)112     pointer reallocate(T* p, size_type oldSize, size_type newSize,
113                        bool preserve)
114     {
115         return StdReallocate(*this, p, oldSize, newSize, preserve);
116     }
117 
118     // VS.NET STL enforces the policy of "All STL-compliant allocators have to
119     // provide a template class member called rebind".
120     template <class U> struct rebind { typedef AllocatorWithCleanup<U> other;};
121 };
122 
123 
124 // Block class template
125 template<typename T, class A = AllocatorWithCleanup<T> >
126 class Block {
127 public:
Block(word32 s=0)128     explicit Block(word32 s = 0) : sz_(s), buffer_(allocator_.allocate(sz_))
129                     { CleanNew(sz_); }
130 
Block(const T * buff,word32 s)131     Block(const T* buff, word32 s) : sz_(s), buffer_(allocator_.allocate(sz_))
132         { memcpy(buffer_, buff, sz_ * sizeof(T)); }
133 
Block(const Block & that)134     Block(const Block& that) : sz_(that.sz_), buffer_(allocator_.allocate(sz_))
135         { memcpy(buffer_, that.buffer_, sz_ * sizeof(T)); }
136 
operator =(const Block & that)137     Block& operator=(const Block& that) {
138         Block tmp(that);
139         Swap(tmp);
140         return *this;
141     }
142 
operator [](word32 i)143     T& operator[] (word32 i) { return buffer_[i]; }
operator [](word32 i) const144     const T& operator[] (word32 i) const { return buffer_[i]; }
145 
operator +(word32 i)146     T* operator+ (word32 i) { return buffer_ + i; }
operator +(word32 i) const147     const T* operator+ (word32 i) const { return buffer_ + i; }
148 
size() const149     word32 size() const { return sz_; }
150 
get_buffer() const151     T* get_buffer() const { return buffer_; }
begin() const152     T* begin()      const { return get_buffer(); }
153 
CleanGrow(word32 newSize)154     void CleanGrow(word32 newSize)
155     {
156         if (newSize > sz_) {
157             buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
158             memset(buffer_ + sz_, 0, (newSize - sz_) * sizeof(T));
159             sz_ = newSize;
160         }
161     }
162 
CleanNew(word32 newSize)163     void CleanNew(word32 newSize)
164     {
165         New(newSize);
166         if (sz_ > 0)
167           memset(buffer_, 0, sz_ * sizeof(T));
168     }
169 
New(word32 newSize)170     void New(word32 newSize)
171     {
172         buffer_ = allocator_.reallocate(buffer_, sz_, newSize, false);
173         sz_ = newSize;
174     }
175 
resize(word32 newSize)176     void resize(word32 newSize)
177     {
178         buffer_ = allocator_.reallocate(buffer_, sz_, newSize, true);
179         sz_ = newSize;
180     }
181 
Swap(Block & other)182     void Swap(Block& other) {
183         STL::swap(sz_, other.sz_);
184         STL::swap(buffer_, other.buffer_);
185         STL::swap(allocator_, other.allocator_);
186     }
187 
~Block()188     ~Block() { allocator_.deallocate(buffer_, sz_); }
189 private:
190     A      allocator_;
191     word32 sz_;     // size in Ts
192     T*     buffer_;
193 };
194 
195 
196 typedef Block<byte>   ByteBlock;
197 typedef Block<word>   WordBlock;
198 typedef Block<word32> Word32Block;
199 
200 
201 } // namespace
202 
203 #endif // TAO_CRYPT_BLOCK_HPP
204