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