1 | /*␊ |
2 | Copyright 2021 Grégory Soutadé␊ |
3 | ␊ |
4 | This file is part of libgourou.␊ |
5 | ␊ |
6 | libgourou is free software: you can redistribute it and/or modify␊ |
7 | it under the terms of the GNU Lesser General Public License as published by␊ |
8 | the Free Software Foundation, either version 3 of the License, or␊ |
9 | (at your option) any later version.␊ |
10 | ␊ |
11 | libgourou is distributed in the hope that it will be useful,␊ |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of␊ |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the␊ |
14 | GNU Lesser General Public License for more details.␊ |
15 | ␊ |
16 | You should have received a copy of the GNU Lesser General Public License␊ |
17 | along with libgourou. If not, see <http://www.gnu.org/licenses/>.␊ |
18 | */␊ |
19 | #include <string.h>␊ |
20 | #include <stdexcept>␊ |
21 | ␊ |
22 | #include <Base64.h>␊ |
23 | ␊ |
24 | #include <bytearray.h>␊ |
25 | ␊ |
26 | namespace gourou␊ |
27 | {␊ |
28 | std::map<unsigned char*, int> ByteArray::refCounter;␊ |
29 | ␊ |
30 | ByteArray::ByteArray(bool useMalloc):_useMalloc(useMalloc), _data(0), _length(0)␊ |
31 | {}␊ |
32 | ␊ |
33 | ByteArray::ByteArray(unsigned int length, bool useMalloc):␊ |
34 | ␉_useMalloc(useMalloc)␊ |
35 | {␊ |
36 | ␉initData(0, length);␊ |
37 | }␊ |
38 | ␊ |
39 | ByteArray::ByteArray(const unsigned char* data, unsigned int length):␊ |
40 | ␉_useMalloc(false)␊ |
41 | {␊ |
42 | ␉initData(data, length);␊ |
43 | }␊ |
44 | ␊ |
45 | ByteArray::ByteArray(const char* data, int length):␊ |
46 | ␉_useMalloc(false)␊ |
47 | {␊ |
48 | ␉if (length == -1)␊ |
49 | ␉ length = strlen(data);␊ |
50 | ␊ |
51 | ␉initData((unsigned char*)data, (unsigned int) length);␊ |
52 | }␊ |
53 | ␊ |
54 | ByteArray::ByteArray(const std::string& str):␊ |
55 | ␉_useMalloc(false)␊ |
56 | {␊ |
57 | ␉initData((unsigned char*)str.c_str(), (unsigned int)str.length());␊ |
58 | }␊ |
59 | ␊ |
60 | void ByteArray::initData(const unsigned char* data, unsigned int length)␊ |
61 | {␊ |
62 | ␉if (_useMalloc)␊ |
63 | ␉ _data = (unsigned char*)malloc(length);␊ |
64 | ␉else␊ |
65 | ␉ _data = new unsigned char[length];␊ |
66 | ␊ |
67 | ␉if (data)␊ |
68 | ␉ memcpy((void*)_data, data, length);␊ |
69 | ␊ |
70 | ␉_length = length;␊ |
71 | ␊ |
72 | ␉addRef();␊ |
73 | }␊ |
74 | ␊ |
75 | ByteArray::ByteArray(const ByteArray& other)␊ |
76 | {␊ |
77 | ␉this->_useMalloc = other._useMalloc;␊ |
78 | ␉this->_data = other._data;␊ |
79 | ␉this->_length = other._length;␊ |
80 | ␊ |
81 | ␉addRef();␊ |
82 | }␊ |
83 | ␊ |
84 | ByteArray& ByteArray::operator=(const ByteArray& other)␊ |
85 | {␊ |
86 | ␉delRef();␊ |
87 | ␉␊ |
88 | ␉this->_useMalloc = other._useMalloc;␊ |
89 | ␉this->_data = other._data;␊ |
90 | ␉this->_length = other._length;␊ |
91 | ␊ |
92 | ␉addRef();␊ |
93 | ␉␊ |
94 | ␉return *this;␊ |
95 | }␊ |
96 | ␊ |
97 | ByteArray::~ByteArray()␊ |
98 | {␊ |
99 | ␉delRef();␊ |
100 | }␊ |
101 | ␉␊ |
102 | void ByteArray::addRef()␊ |
103 | {␊ |
104 | ␉if (!_data) return;␊ |
105 | ␊ |
106 | ␉if (refCounter.count(_data) == 0)␊ |
107 | ␉ refCounter[_data] = 1;␊ |
108 | ␉else␊ |
109 | ␉ refCounter[_data]++;␊ |
110 | }␊ |
111 | ␊ |
112 | void ByteArray::delRef()␊ |
113 | {␊ |
114 | ␉if (!_data) return;␊ |
115 | ␉␊ |
116 | ␉if (refCounter[_data] == 1)␊ |
117 | ␉{␊ |
118 | ␉ if (_useMalloc)␊ |
119 | ␉␉free(_data);␊ |
120 | ␉ else␊ |
121 | ␉␉delete[] _data;␊ |
122 | ␉ refCounter.erase(_data);␊ |
123 | ␉}␊ |
124 | ␉else␊ |
125 | ␉ refCounter[_data]--;␊ |
126 | }␊ |
127 | ␊ |
128 | ByteArray ByteArray::fromBase64(const ByteArray& other)␊ |
129 | {␊ |
130 | ␉std::string b64;␊ |
131 | ␊ |
132 | ␉macaron::Base64::Decode(std::string((char*)other._data, other._length), b64);␊ |
133 | ␊ |
134 | ␉return ByteArray(b64);␊ |
135 | }␊ |
136 | ␊ |
137 | ByteArray ByteArray::fromBase64(const char* data, int length)␊ |
138 | {␊ |
139 | ␉std::string b64;␊ |
140 | ␊ |
141 | ␉if (length == -1)␊ |
142 | ␉ length = strlen(data);␊ |
143 | ␉␊ |
144 | ␉macaron::Base64::Decode(std::string(data, length), b64);␊ |
145 | ␊ |
146 | ␉return ByteArray(b64);␊ |
147 | }␊ |
148 | ␊ |
149 | ByteArray ByteArray::fromBase64(const std::string& str)␊ |
150 | {␊ |
151 | ␉return ByteArray::fromBase64(str.c_str(), str.length());␊ |
152 | }␊ |
153 | ␊ |
154 | std::string ByteArray::toBase64()␊ |
155 | {␊ |
156 | ␉return macaron::Base64::Encode(std::string((char*)_data, _length));␊ |
157 | }␊ |
158 | ␊ |
159 | ByteArray ByteArray::fromHex(const std::string& str)␊ |
160 | {␊ |
161 | ␉if (str.size() % 2)␊ |
162 | ␉ throw std::invalid_argument("Size of hex string not multiple of 2");␊ |
163 | ␊ |
164 | ␉ByteArray res((unsigned int)(str.size()/2));␊ |
165 | ␉unsigned int i;␊ |
166 | ␊ |
167 | ␉unsigned char* data = res.data();␊ |
168 | ␉unsigned char cur, tmp;␊ |
169 | ␉␊ |
170 | ␉for (i=0; i<str.size(); i+=2)␊ |
171 | ␉{␊ |
172 | ␉ cur = 0;␊ |
173 | ␊ |
174 | ␉ tmp = str[i];␊ |
175 | ␉ if (tmp >= 'a' && tmp <= 'f')␊ |
176 | ␉␉cur = (tmp - 'a' + 10) << 4;␊ |
177 | ␉ else if (tmp >= 'A' && tmp <= 'F')␊ |
178 | ␉␉cur = (tmp - 'A' + 10) << 4;␊ |
179 | ␉ else if (tmp >= '0' && tmp <= '9')␊ |
180 | ␉␉cur = (tmp - '0') << 4;␊ |
181 | ␉ else␊ |
182 | ␉␉throw std::invalid_argument("Invalid character in hex string");␊ |
183 | ␊ |
184 | ␉ tmp = str[i+1];␊ |
185 | ␉ if (tmp >= 'a' && tmp <= 'f')␊ |
186 | ␉␉cur += tmp - 'a' + 10;␊ |
187 | ␉ else if (tmp >= 'A' && tmp <= 'F')␊ |
188 | ␉␉cur += tmp - 'A' + 10;␊ |
189 | ␉ else if (tmp >= '0' && tmp <= '9')␊ |
190 | ␉␉cur += tmp - '0';␊ |
191 | ␉ else␊ |
192 | ␉␉throw std::invalid_argument("Invalid character in hex string");␊ |
193 | ␊ |
194 | ␉ data[i/2] = cur;␊ |
195 | ␉}␊ |
196 | ␉␊ |
197 | ␉return res;␊ |
198 | }␊ |
199 | ␊ |
200 | std::string ByteArray::toHex()␊ |
201 | {␊ |
202 | ␉char* tmp = new char[_length*2+1];␊ |
203 | ␊ |
204 | ␉for(int i=0; i<(int)_length; i++)␊ |
205 | ␉ sprintf(&tmp[i*2], "%02x", _data[i]);␊ |
206 | ␊ |
207 | ␉tmp[_length*2] = 0;␊ |
208 | ␊ |
209 | ␉std::string res = tmp;␊ |
210 | ␉delete[] tmp;␊ |
211 | ␉␊ |
212 | ␉return res;␊ |
213 | }␊ |
214 | ␊ |
215 | void ByteArray::append(const unsigned char* data, unsigned int length)␊ |
216 | {␊ |
217 | ␉if (!length)␊ |
218 | ␉ return;␊ |
219 | ␉␊ |
220 | ␉unsigned int oldLength = _length;␊ |
221 | ␊ |
222 | ␉resize(_length+length, true);␊ |
223 | ␊ |
224 | ␉memcpy(&_data[oldLength], data, length);␉␊ |
225 | }␊ |
226 | ␊ |
227 | void ByteArray::append(unsigned char c) { append(&c, 1);}␊ |
228 | void ByteArray::append(const char* str) { append((const unsigned char*)str, strlen(str));}␊ |
229 | void ByteArray::append(const std::string& str) { append((const unsigned char*)str.c_str(), str.length()); }␊ |
230 | ␊ |
231 | void ByteArray::resize(unsigned length, bool keepData)␊ |
232 | {␊ |
233 | ␉if (length == _length)␊ |
234 | ␉ return;␊ |
235 | ␉else if (length < _length)␊ |
236 | ␉ _length = length ; // Don't touch data␊ |
237 | ␉else // New size >␊ |
238 | ␉{␊ |
239 | ␉ unsigned char* newData;␊ |
240 | ␊ |
241 | ␉ if (_useMalloc)␊ |
242 | ␉␉newData = (unsigned char*)malloc(_length+length);␊ |
243 | ␉ else␊ |
244 | ␉␉newData = new unsigned char[_length+length];␊ |
245 | ␊ |
246 | ␉ if (keepData)␊ |
247 | ␉␉memcpy(newData, _data, _length);␊ |
248 | ␉␊ |
249 | ␉ delRef();␊ |
250 | ␊ |
251 | ␉ _length = length;␊ |
252 | ␉ _data = newData;␊ |
253 | ␉␊ |
254 | ␉ addRef();␊ |
255 | ␉}␊ |
256 | }␊ |
257 | }␊ |