1 /*
2  * This file is part of LibParserUtils.
3  * Licensed under the MIT License,
4  *                http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
6  */
7 
8 #include <string.h>
9 
10 #include <parserutils/utils/buffer.h>
11 
12 #define DEFAULT_SIZE (4096)
13 
14 /**
15  * Create a memory buffer
16  *
17  * \param buffer  Pointer to location to receive memory buffer
18  * \return PARSERUTILS_OK on success,
19  *         PARSERUTILS_BADPARM on bad parameters,
20  *         PARSERUTILS_NOMEM on memory exhausion
21  */
parserutils_buffer_create(parserutils_buffer ** buffer)22 parserutils_error parserutils_buffer_create(parserutils_buffer **buffer)
23 {
24 	parserutils_buffer *b;
25 
26 	if (buffer == NULL)
27 		return PARSERUTILS_BADPARM;
28 
29 	b = malloc(sizeof(parserutils_buffer));
30 	if (b == NULL)
31 		return PARSERUTILS_NOMEM;
32 
33 	b->data = malloc(DEFAULT_SIZE);
34 	if (b->data == NULL) {
35 		free(b);
36 		return PARSERUTILS_NOMEM;
37 	}
38 
39 	b->length = 0;
40 	b->allocated = DEFAULT_SIZE;
41 
42 	*buffer = b;
43 
44 	return PARSERUTILS_OK;
45 }
46 
47 /**
48  * Destroy a memory buffer
49  *
50  * \param buffer  The buffer to destroy
51  * \return PARSERUTILS_OK on success, appropriate error otherwise
52  */
parserutils_buffer_destroy(parserutils_buffer * buffer)53 parserutils_error parserutils_buffer_destroy(parserutils_buffer *buffer)
54 {
55 	if (buffer == NULL)
56 		return PARSERUTILS_BADPARM;
57 
58 	free(buffer->data);
59 	free(buffer);
60 
61 	return PARSERUTILS_OK;
62 }
63 
64 /**
65  * Append data to a memory buffer
66  *
67  * \param buffer  The buffer to append to
68  * \param data    The data to append
69  * \param len     The length, in bytes, of the data to append
70  * \return PARSERUTILS_OK on success, appropriate error otherwise.
71  */
parserutils_buffer_append(parserutils_buffer * buffer,const uint8_t * data,size_t len)72 parserutils_error parserutils_buffer_append(parserutils_buffer *buffer,
73 		const uint8_t *data, size_t len)
74 {
75 	while (len >= buffer->allocated - buffer->length) {
76 		parserutils_error error = parserutils_buffer_grow(buffer);
77 		if (error != PARSERUTILS_OK)
78 			return error;
79 	}
80 
81 	memcpy(buffer->data + buffer->length, data, len);
82 
83 	buffer->length += len;
84 
85 	return PARSERUTILS_OK;
86 }
87 
88 /**
89  * Insert data into a memory buffer
90  *
91  * \param buffer  The buffer to insert into
92  * \param offset  The offset into the buffer to insert at
93  * \param data    The data to insert
94  * \param len     The length, in bytes, of the data to insert
95  * \return PARSERUTILS_OK on success, appropriate error otherwise
96  */
parserutils_buffer_insert(parserutils_buffer * buffer,size_t offset,const uint8_t * data,size_t len)97 parserutils_error parserutils_buffer_insert(parserutils_buffer *buffer,
98 		size_t offset, const uint8_t *data, size_t len)
99 {
100 	if (offset > buffer->length)
101 		return PARSERUTILS_BADPARM;
102 
103 	if (offset == buffer->length)
104 		return parserutils_buffer_append(buffer, data, len);
105 
106 	while (len >= buffer->allocated - buffer->length) {
107 		parserutils_error error = parserutils_buffer_grow(buffer);
108 		if (error != PARSERUTILS_OK)
109 			return error;
110 	}
111 
112 	memmove(buffer->data + offset + len,
113 			buffer->data + offset, buffer->length - offset);
114 
115 	memcpy(buffer->data + offset, data, len);
116 
117 	buffer->length += len;
118 
119 	return PARSERUTILS_OK;
120 }
121 
122 /**
123  * Discard a section of a memory buffer
124  *
125  * \param buffer  The buffer to discard data from
126  * \param offset  The offset into the buffer of the start of the section
127  * \param len     The number of bytes to discard
128  * \return PARSERUTILS_OK on success, appropriate error otherwise.
129  */
parserutils_buffer_discard(parserutils_buffer * buffer,size_t offset,size_t len)130 parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer,
131 		size_t offset, size_t len)
132 {
133 	if (offset >= buffer->length || offset + len > buffer->length)
134 		return PARSERUTILS_BADPARM;
135 
136 	memmove(buffer->data + offset, buffer->data + offset + len,
137 			buffer->length - (len + offset));
138 
139 	buffer->length -= len;
140 
141 	return PARSERUTILS_OK;
142 }
143 
144 /**
145  * Extend the amount of space allocated for a memory buffer
146  *
147  * \param buffer  The buffer to extend
148  * \return PARSERUTILS_OK on success, appropriate error otherwise.
149  */
parserutils_buffer_grow(parserutils_buffer * buffer)150 parserutils_error parserutils_buffer_grow(parserutils_buffer *buffer)
151 {
152 	uint8_t *temp = realloc(buffer->data, buffer->allocated * 2);
153 	if (temp == NULL)
154 		return PARSERUTILS_NOMEM;
155 
156 	buffer->data = temp;
157 	buffer->allocated *= 2;
158 
159 	return PARSERUTILS_OK;
160 }
161 
parserutils_buffer_randomise(parserutils_buffer * buffer)162 parserutils_error parserutils_buffer_randomise(parserutils_buffer *buffer)
163 {
164 #ifndef NDEBUG
165 	uint8_t *temp;
166 #endif
167 
168 	if (buffer == NULL)
169 		return PARSERUTILS_BADPARM;
170 
171 #ifndef NDEBUG
172 	temp = malloc(buffer->allocated);
173 	if (temp == NULL)
174 		return PARSERUTILS_NOMEM;
175 
176 	memcpy(temp, buffer->data, buffer->length);
177 
178 	memset(buffer->data, 0xff, buffer->length);
179 
180 	/* Leak the buffer's current data, so we don't reuse it */
181 	/* buffer->alloc(buffer->data, 0, buffer->pw); */
182 
183 	buffer->data = temp;
184 #endif
185 
186 
187 	return PARSERUTILS_OK;
188 }
189 
190