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