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