1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information
3
4 #include <rudiments/bytebuffer.h>
5 #include <rudiments/charstring.h>
6 #include <rudiments/bytestring.h>
7
8 #ifdef RUDIMENTS_HAVE_STRING_H
9 #include <string.h>
10 #endif
11
12 #ifdef RUDIMENTS_HAVE_VASPRINTF
13 #include <stdio.h>
14 #ifdef RUDIMENTS_HAVE_STDLIB_H
15 #include <stdlib.h>
16 #endif
17 #endif
18
19 #define DEFAULT_INITIALSIZE 32
20
21 class bytebufferprivate {
22 friend class bytebuffer;
23 private:
24 unsigned char * _buffer;
25 size_t _size;
26 size_t _actualsize;
27 size_t _pos;
28 size_t _initialsize;
29 };
30
bytebuffer()31 bytebuffer::bytebuffer() {
32 init(NULL,DEFAULT_INITIALSIZE);
33 }
34
bytebuffer(size_t initialsize)35 bytebuffer::bytebuffer(size_t initialsize) {
36 init(NULL,initialsize);
37 }
38
bytebuffer(unsigned char * initialcontents,size_t initialsize)39 bytebuffer::bytebuffer(unsigned char *initialcontents, size_t initialsize) {
40 init(initialcontents,initialsize);
41 }
42
init(unsigned char * initialcontents,size_t initialsize)43 void bytebuffer::init(unsigned char *initialcontents, size_t initialsize) {
44 if (!initialsize) {
45 initialsize=DEFAULT_INITIALSIZE;
46 }
47 pvt=new bytebufferprivate;
48 if (initialcontents) {
49 pvt->_buffer=initialcontents;
50 pvt->_size=initialsize;
51 pvt->_pos=initialsize;
52 } else {
53 pvt->_buffer=new unsigned char[initialsize];
54 pvt->_size=0;
55 pvt->_pos=0;
56 }
57 pvt->_actualsize=initialsize;
58 pvt->_initialsize=initialsize;
59 }
60
bytebuffer(const bytebuffer & v)61 bytebuffer::bytebuffer(const bytebuffer &v) {
62 bytebufferClone(v);
63 }
64
operator =(const bytebuffer & v)65 bytebuffer &bytebuffer::operator=(const bytebuffer &v) {
66 if (this!=&v) {
67 delete[] pvt->_buffer;
68 delete pvt;
69 bytebufferClone(v);
70 }
71 return *this;
72 }
73
~bytebuffer()74 bytebuffer::~bytebuffer() {
75 delete[] pvt->_buffer;
76 delete pvt;
77 }
78
bytebufferClone(const bytebuffer & v)79 void bytebuffer::bytebufferClone(const bytebuffer &v) {
80 pvt=new bytebufferprivate;
81 pvt->_buffer=(unsigned char *)bytestring::duplicate(
82 v.pvt->_buffer,v.pvt->_size);
83 pvt->_size=v.pvt->_size;
84 pvt->_actualsize=v.pvt->_actualsize;
85 pvt->_pos=v.pvt->_pos;
86 pvt->_initialsize=v.pvt->_initialsize;
87 }
88
read(unsigned char * data,size_t size)89 ssize_t bytebuffer::read(unsigned char *data, size_t size) {
90
91 if (size>pvt->_size-pvt->_pos) {
92 size=pvt->_size-pvt->_pos;
93 }
94
95 // bail if we're not actually copying anything or if
96 // the current position is set to or set beyond the end
97 if (!size || pvt->_pos>=pvt->_size) {
98 return 0;
99 }
100
101 memcpy(data,pvt->_buffer+pvt->_pos,size);
102 pvt->_pos+=size;
103 return size;
104 }
105
write(const unsigned char * data,size_t size)106 ssize_t bytebuffer::write(const unsigned char *data, size_t size) {
107 size_t finalpos=pvt->_pos+size;
108 if (finalpos>pvt->_actualsize) {
109 extend(finalpos);
110 }
111 memcpy(pvt->_buffer+pvt->_pos,data,size);
112 pvt->_pos=finalpos;
113 if (finalpos>pvt->_size) {
114 pvt->_size=finalpos;
115 }
116 return size;
117 }
118
extend(size_t requiredsize)119 void bytebuffer::extend(size_t requiredsize) {
120
121 do {
122 pvt->_actualsize=pvt->_actualsize*3/2;
123 } while (requiredsize>pvt->_actualsize);
124
125 // FIXME: we need a growth cap
126
127 unsigned char *newbuffer=new unsigned char[pvt->_actualsize];
128 memcpy(newbuffer,pvt->_buffer,pvt->_size);
129 delete[] pvt->_buffer;
130 pvt->_buffer=newbuffer;
131 }
132
write(const char * string,size_t size)133 ssize_t bytebuffer::write(const char *string, size_t size) {
134 return write(reinterpret_cast<const unsigned char *>(string),size);
135 }
136
write(const char * string)137 ssize_t bytebuffer::write(const char *string) {
138 return write(reinterpret_cast<const unsigned char *>(string),
139 charstring::length(string));
140 }
141
write(char character)142 ssize_t bytebuffer::write(char character) {
143 return write(reinterpret_cast<const unsigned char *>(&character),
144 sizeof(char));
145 }
146
write(int16_t number)147 ssize_t bytebuffer::write(int16_t number) {
148 return write(reinterpret_cast<const unsigned char *>(&number),
149 sizeof(int16_t));
150 }
151
write(int32_t number)152 ssize_t bytebuffer::write(int32_t number) {
153 return write(reinterpret_cast<const unsigned char *>(&number),
154 sizeof(int32_t));
155 }
156
write(int64_t number)157 ssize_t bytebuffer::write(int64_t number) {
158 return write(reinterpret_cast<const unsigned char *>(&number),
159 sizeof(int64_t));
160 }
161
write(unsigned char character)162 ssize_t bytebuffer::write(unsigned char character) {
163 return write(reinterpret_cast<const unsigned char *>(&character),
164 sizeof(unsigned char));
165 }
166
write(uint16_t number)167 ssize_t bytebuffer::write(uint16_t number) {
168 return write(reinterpret_cast<const unsigned char *>(&number),
169 sizeof(uint16_t));
170 }
171
write(uint32_t number)172 ssize_t bytebuffer::write(uint32_t number) {
173 return write(reinterpret_cast<const unsigned char *>(&number),
174 sizeof(uint32_t));
175 }
176
write(uint64_t number)177 ssize_t bytebuffer::write(uint64_t number) {
178 return write(reinterpret_cast<const unsigned char *>(&number),
179 sizeof(uint64_t));
180 }
181
write(float number)182 ssize_t bytebuffer::write(float number) {
183 return write(reinterpret_cast<const unsigned char *>(&number),
184 sizeof(float));
185 }
186
write(double number)187 ssize_t bytebuffer::write(double number) {
188 return write(reinterpret_cast<const unsigned char *>(&number),
189 sizeof(double));
190 }
191
writeFormatted(const char * format,...)192 ssize_t bytebuffer::writeFormatted(const char *format, ...) {
193 va_list argp;
194 va_start(argp,format);
195 ssize_t retval=writeFormatted(format,&argp);
196 va_end(argp);
197 return retval;
198 }
199
writeFormatted(const char * format,va_list * argp)200 ssize_t bytebuffer::writeFormatted(const char *format, va_list *argp) {
201
202 // write the formatted data to a buffer
203 char *buffer=NULL;
204 ssize_t size=0;
205 #ifdef RUDIMENTS_HAVE_VASPRINTF
206 size=vasprintf(&buffer,format,*argp);
207 #else
208 size=charstring::printf(&buffer,format,argp);
209 #endif
210
211 // extend the list of buffers to accommodate
212 // "size" bytes beyond the current position
213 if (pvt->_pos+size>pvt->_actualsize) {
214 extend(pvt->_pos+size);
215 }
216
217 // write the buffer
218 write(buffer,size);
219
220 // clean up
221 #ifdef RUDIMENTS_HAVE_VASPRINTF
222 free(buffer);
223 #else
224 delete[] buffer;
225 #endif
226
227 return size;
228 }
229
clear()230 void bytebuffer::clear() {
231 pvt->_size=0;
232 pvt->_pos=0;
233 }
234
clear(size_t initialsize)235 void bytebuffer::clear(size_t initialsize) {
236 delete[] pvt->_buffer;
237 pvt->_buffer=new unsigned char[initialsize];
238 pvt->_size=0;
239 pvt->_actualsize=initialsize;
240 pvt->_pos=0;
241 pvt->_initialsize=initialsize;
242 }
243
clear(unsigned char * initialcontents,size_t initialsize)244 void bytebuffer::clear(unsigned char *initialcontents, size_t initialsize) {
245 delete[] pvt->_buffer;
246 pvt->_buffer=initialcontents;
247 pvt->_size=initialsize;
248 pvt->_actualsize=initialsize;
249 pvt->_pos=initialsize;
250 pvt->_initialsize=initialsize;
251 }
252
getBuffer()253 const unsigned char *bytebuffer::getBuffer() {
254 return pvt->_buffer;
255 }
256
detachBuffer()257 unsigned char *bytebuffer::detachBuffer() {
258 unsigned char *buffer=pvt->_buffer;
259 pvt->_buffer=new unsigned char[pvt->_initialsize];
260 pvt->_size=0;
261 pvt->_actualsize=pvt->_initialsize;
262 pvt->_pos=0;
263 return buffer;
264 }
265
getSize()266 size_t bytebuffer::getSize() {
267 return pvt->_size;
268 }
269
getPosition()270 size_t bytebuffer::getPosition() {
271 return pvt->_pos;
272 }
273
getActualSize()274 size_t bytebuffer::getActualSize() {
275 return pvt->_actualsize;
276 }
277
getInitialSize()278 size_t bytebuffer::getInitialSize() {
279 return pvt->_initialsize;
280 }
281
setPosition(size_t pos)282 void bytebuffer::setPosition(size_t pos) {
283 pvt->_pos=pos;
284 }
285
append(const unsigned char * data,size_t size)286 bytebuffer *bytebuffer::append(const unsigned char *data, size_t size) {
287 if (pvt->_size+size>pvt->_actualsize) {
288 extend(pvt->_size+size);
289 }
290 memcpy(pvt->_buffer+pvt->_size,data,size);
291 pvt->_size+=size;
292 pvt->_pos=pvt->_size;
293 return this;
294 }
295
append(const char * data,size_t size)296 bytebuffer *bytebuffer::append(const char *data, size_t size) {
297 if (pvt->_size+size>pvt->_actualsize) {
298 extend(pvt->_size+size);
299 }
300 memcpy(pvt->_buffer+pvt->_size,data,size);
301 pvt->_size+=size;
302 pvt->_pos=pvt->_size;
303 return this;
304 }
305
append(const char * string)306 bytebuffer *bytebuffer::append(const char *string) {
307 return append(reinterpret_cast<const unsigned char *>(string),
308 charstring::length(string));
309 }
310
append(char character)311 bytebuffer *bytebuffer::append(char character) {
312 return append(reinterpret_cast<const unsigned char *>(&character),
313 sizeof(char));
314 }
315
append(int16_t number)316 bytebuffer *bytebuffer::append(int16_t number) {
317 return append(reinterpret_cast<const unsigned char *>(&number),
318 sizeof(int16_t));
319 }
320
append(int32_t number)321 bytebuffer *bytebuffer::append(int32_t number) {
322 return append(reinterpret_cast<const unsigned char *>(&number),
323 sizeof(int32_t));
324 }
325
append(int64_t number)326 bytebuffer *bytebuffer::append(int64_t number) {
327 return append(reinterpret_cast<const unsigned char *>(&number),
328 sizeof(int64_t));
329 }
330
append(unsigned char character)331 bytebuffer *bytebuffer::append(unsigned char character) {
332 return append(reinterpret_cast<const unsigned char *>(&character),
333 sizeof(unsigned char));
334 }
335
append(uint16_t number)336 bytebuffer *bytebuffer::append(uint16_t number) {
337 return append(reinterpret_cast<const unsigned char *>(&number),
338 sizeof(uint16_t));
339 }
340
append(uint32_t number)341 bytebuffer *bytebuffer::append(uint32_t number) {
342 return append(reinterpret_cast<const unsigned char *>(&number),
343 sizeof(uint32_t));
344 }
345
append(uint64_t number)346 bytebuffer *bytebuffer::append(uint64_t number) {
347 return append(reinterpret_cast<const unsigned char *>(&number),
348 sizeof(uint64_t));
349 }
350
append(float number)351 bytebuffer *bytebuffer::append(float number) {
352 return append(reinterpret_cast<const unsigned char *>(&number),
353 sizeof(float));
354 }
355
append(double number)356 bytebuffer *bytebuffer::append(double number) {
357 return append(reinterpret_cast<const unsigned char *>(&number),
358 sizeof(double));
359 }
360
appendFormatted(const char * format,...)361 bytebuffer *bytebuffer::appendFormatted(const char *format, ...) {
362 va_list argp;
363 va_start(argp,format);
364 bytebuffer *retval=appendFormatted(format,&argp);
365 va_end(argp);
366 return retval;
367 }
368
appendFormatted(const char * format,va_list * argp)369 bytebuffer *bytebuffer::appendFormatted(const char *format, va_list *argp) {
370 pvt->_pos=pvt->_size;
371 writeFormatted(format,argp);
372 return this;
373 }
374
truncate(size_t pos)375 void bytebuffer::truncate(size_t pos) {
376 pvt->_size=pos;
377 }
378
truncate()379 void bytebuffer::truncate() {
380 pvt->_size=pvt->_pos;
381 }
382
_size()383 size_t bytebuffer::_size() {
384 return pvt->_size;
385 }
386
_size(size_t s)387 void bytebuffer::_size(size_t s) {
388 pvt->_size=s;
389 }
390
_position()391 size_t bytebuffer::_position() {
392 return pvt->_pos;
393 }
394
_position(size_t pos)395 void bytebuffer::_position(size_t pos) {
396 setPosition(pos);
397 }
398