1 /***********************************************************************************************************************************
2 Buffer Handler
3 ***********************************************************************************************************************************/
4 #include "build.auto.h"
5
6 #include <stdio.h>
7 #include <string.h>
8
9 #include "common/debug.h"
10 #include "common/type/buffer.h"
11
12 /***********************************************************************************************************************************
13 Constant buffers that are generally useful
14 ***********************************************************************************************************************************/
15 BUFFER_STRDEF_EXTERN(BRACEL_BUF, BRACEL_Z);
16 BUFFER_STRDEF_EXTERN(BRACER_BUF, BRACER_Z);
17 BUFFER_STRDEF_EXTERN(BRACKETL_BUF, BRACKETL_Z);
18 BUFFER_STRDEF_EXTERN(BRACKETR_BUF, BRACKETR_Z);
19 BUFFER_STRDEF_EXTERN(COMMA_BUF, COMMA_Z);
20 BUFFER_STRDEF_EXTERN(CR_BUF, CR_Z);
21 BUFFER_STRDEF_EXTERN(DOT_BUF, DOT_Z);
22 BUFFER_STRDEF_EXTERN(EQ_BUF, EQ_Z);
23 BUFFER_STRDEF_EXTERN(LF_BUF, LF_Z);
24 BUFFER_STRDEF_EXTERN(QUOTED_BUF, QUOTED_Z);
25
26 /***********************************************************************************************************************************
27 Contains information about the buffer
28 ***********************************************************************************************************************************/
29 struct Buffer
30 {
31 BufferPub pub; // Publicly accessible variables
32 };
33
34 /**********************************************************************************************************************************/
35 Buffer *
bufNew(size_t size)36 bufNew(size_t size)
37 {
38 FUNCTION_TEST_BEGIN();
39 FUNCTION_TEST_PARAM(SIZE, size);
40 FUNCTION_TEST_END();
41
42 Buffer *this = NULL;
43
44 MEM_CONTEXT_NEW_BEGIN("Buffer")
45 {
46 // Create object
47 this = memNew(sizeof(Buffer));
48
49 *this = (Buffer)
50 {
51 .pub =
52 {
53 .memContext = MEM_CONTEXT_NEW(),
54 .sizeAlloc = size,
55 .size = size,
56 },
57 };
58
59 // Allocate buffer
60 if (size > 0)
61 this->pub.buffer = memNew(this->pub.sizeAlloc);
62 }
63 MEM_CONTEXT_NEW_END();
64
65 FUNCTION_TEST_RETURN(this);
66 }
67
68 /**********************************************************************************************************************************/
69 Buffer *
bufNewC(const void * buffer,size_t size)70 bufNewC(const void *buffer, size_t size)
71 {
72 FUNCTION_TEST_BEGIN();
73 FUNCTION_TEST_PARAM_P(VOID, buffer);
74 FUNCTION_TEST_PARAM(SIZE, size);
75 FUNCTION_TEST_END();
76
77 ASSERT(buffer != NULL);
78
79 // Create object and copy data
80 Buffer *this = bufNew(size);
81 memcpy(this->pub.buffer, buffer, bufSize(this));
82 this->pub.used = bufSize(this);
83
84 FUNCTION_TEST_RETURN(this);
85 }
86
87 /**********************************************************************************************************************************/
88 Buffer *
bufNewDecode(EncodeType type,const String * string)89 bufNewDecode(EncodeType type, const String *string)
90 {
91 FUNCTION_TEST_BEGIN();
92 FUNCTION_TEST_PARAM(ENUM, type);
93 FUNCTION_TEST_PARAM(STRING, string);
94 FUNCTION_TEST_END();
95
96 Buffer *this = bufNew(decodeToBinSize(type, strZ(string)));
97
98 decodeToBin(type, strZ(string), bufPtr(this));
99 bufUsedSet(this, bufSize(this));
100
101 FUNCTION_TEST_RETURN(this);
102 }
103
104 /**********************************************************************************************************************************/
105 Buffer *
bufDup(const Buffer * buffer)106 bufDup(const Buffer *buffer)
107 {
108 FUNCTION_TEST_BEGIN();
109 FUNCTION_TEST_PARAM(BUFFER, buffer);
110 FUNCTION_TEST_END();
111
112 ASSERT(buffer != NULL);
113
114 // Create object and copy data
115 Buffer *this = bufNew(buffer->pub.used);
116 memcpy(this->pub.buffer, buffer->pub.buffer, bufSize(this));
117 this->pub.used = bufSize(this);
118
119 FUNCTION_TEST_RETURN(this);
120 }
121
122 /**********************************************************************************************************************************/
123 Buffer *
bufCat(Buffer * this,const Buffer * cat)124 bufCat(Buffer *this, const Buffer *cat)
125 {
126 FUNCTION_TEST_BEGIN();
127 FUNCTION_TEST_PARAM(BUFFER, this);
128 FUNCTION_TEST_PARAM(BUFFER, cat);
129 FUNCTION_TEST_END();
130
131 ASSERT(this != NULL);
132
133 if (cat != NULL)
134 bufCatC(this, cat->pub.buffer, 0, cat->pub.used);
135
136 FUNCTION_TEST_RETURN(this);
137 }
138
139 /**********************************************************************************************************************************/
140 Buffer *
bufCatC(Buffer * this,const unsigned char * cat,size_t catOffset,size_t catSize)141 bufCatC(Buffer *this, const unsigned char *cat, size_t catOffset, size_t catSize)
142 {
143 FUNCTION_TEST_BEGIN();
144 FUNCTION_TEST_PARAM(BUFFER, this);
145 FUNCTION_TEST_PARAM_P(UCHARDATA, cat);
146 FUNCTION_TEST_PARAM(SIZE, catOffset);
147 FUNCTION_TEST_PARAM(SIZE, catSize);
148 FUNCTION_TEST_END();
149
150 ASSERT(this != NULL);
151 ASSERT(catSize == 0 || cat != NULL);
152
153 if (catSize > 0)
154 {
155 if (bufUsed(this) + catSize > bufSize(this))
156 bufResize(this, bufUsed(this) + catSize);
157
158 // Just here to silence nonnull warnings from clang static analyzer
159 ASSERT(bufPtr(this) != NULL);
160
161 memcpy(bufPtr(this) + bufUsed(this), cat + catOffset, catSize);
162 this->pub.used += catSize;
163 }
164
165 FUNCTION_TEST_RETURN(this);
166 }
167
168 /**********************************************************************************************************************************/
169 Buffer *
bufCatSub(Buffer * this,const Buffer * cat,size_t catOffset,size_t catSize)170 bufCatSub(Buffer *this, const Buffer *cat, size_t catOffset, size_t catSize)
171 {
172 FUNCTION_TEST_BEGIN();
173 FUNCTION_TEST_PARAM(BUFFER, this);
174 FUNCTION_TEST_PARAM(BUFFER, cat);
175 FUNCTION_TEST_PARAM(SIZE, catOffset);
176 FUNCTION_TEST_PARAM(SIZE, catSize);
177 FUNCTION_TEST_END();
178
179 ASSERT(this != NULL);
180
181 if (cat != NULL)
182 {
183 ASSERT(catOffset <= cat->pub.used);
184 ASSERT(catSize <= cat->pub.used - catOffset);
185
186 bufCatC(this, cat->pub.buffer, catOffset, catSize);
187 }
188
189 FUNCTION_TEST_RETURN(this);
190 }
191
192 /**********************************************************************************************************************************/
193 bool
bufEq(const Buffer * this,const Buffer * compare)194 bufEq(const Buffer *this, const Buffer *compare)
195 {
196 FUNCTION_TEST_BEGIN();
197 FUNCTION_TEST_PARAM(BUFFER, this);
198 FUNCTION_TEST_PARAM(BUFFER, compare);
199 FUNCTION_TEST_END();
200
201 ASSERT(this != NULL);
202 ASSERT(compare != NULL);
203
204 if (bufUsed(this) == bufUsed(compare))
205 FUNCTION_TEST_RETURN(memcmp(bufPtrConst(this), bufPtrConst(compare), bufUsed(compare)) == 0);
206
207 FUNCTION_TEST_RETURN(false);
208 }
209
210 /**********************************************************************************************************************************/
211 String *
bufHex(const Buffer * this)212 bufHex(const Buffer *this)
213 {
214 FUNCTION_TEST_BEGIN();
215 FUNCTION_TEST_PARAM(BUFFER, this);
216 FUNCTION_TEST_END();
217
218 ASSERT(this != NULL);
219
220 String *result = strNew();
221
222 for (unsigned int bufferIdx = 0; bufferIdx < bufUsed(this); bufferIdx++)
223 strCatFmt(result, "%02x", bufPtrConst(this)[bufferIdx]);
224
225 FUNCTION_TEST_RETURN(result);
226 }
227
228 /**********************************************************************************************************************************/
229 Buffer *
bufResize(Buffer * this,size_t size)230 bufResize(Buffer *this, size_t size)
231 {
232 FUNCTION_TEST_BEGIN();
233 FUNCTION_TEST_PARAM(BUFFER, this);
234 FUNCTION_TEST_PARAM(SIZE, size);
235 FUNCTION_TEST_END();
236
237 ASSERT(this != NULL);
238
239 // Only resize if it the new size is different
240 if (bufSizeAlloc(this) != size)
241 {
242 // If new size is zero then free memory if allocated
243 if (size == 0)
244 {
245 // When setting size down to 0 the buffer should always be allocated
246 ASSERT(bufPtrConst(this) != NULL);
247
248 MEM_CONTEXT_BEGIN(this->pub.memContext)
249 {
250 memFree(bufPtr(this));
251 }
252 MEM_CONTEXT_END();
253
254 this->pub.buffer = NULL;
255 this->pub.sizeAlloc = 0;
256 }
257 // Else allocate or resize
258 else
259 {
260 MEM_CONTEXT_BEGIN(this->pub.memContext)
261 {
262 if (bufPtrConst(this) == NULL)
263 this->pub.buffer = memNew(size);
264 else
265 this->pub.buffer = memResize(bufPtr(this), size);
266 }
267 MEM_CONTEXT_END();
268
269 this->pub.sizeAlloc = size;
270 }
271
272 if (bufUsed(this) > bufSizeAlloc(this))
273 this->pub.used = bufSizeAlloc(this);
274
275 if (!bufSizeLimit(this))
276 this->pub.size = bufSizeAlloc(this);
277 else if (bufSize(this) > bufSizeAlloc(this))
278 this->pub.size = bufSizeAlloc(this);
279 }
280
281 FUNCTION_TEST_RETURN(this);
282 }
283
284 /**********************************************************************************************************************************/
285 void
bufLimitClear(Buffer * this)286 bufLimitClear(Buffer *this)
287 {
288 FUNCTION_TEST_BEGIN();
289 FUNCTION_TEST_PARAM(BUFFER, this);
290 FUNCTION_TEST_END();
291
292 ASSERT(this != NULL);
293
294 this->pub.sizeLimit = false;
295 this->pub.size = bufSizeAlloc(this);
296
297 FUNCTION_TEST_RETURN_VOID();
298 }
299
300 void
bufLimitSet(Buffer * this,size_t limit)301 bufLimitSet(Buffer *this, size_t limit)
302 {
303 FUNCTION_TEST_BEGIN();
304 FUNCTION_TEST_PARAM(BUFFER, this);
305 FUNCTION_TEST_PARAM(SIZE, limit);
306 FUNCTION_TEST_END();
307
308 ASSERT(this != NULL);
309 ASSERT(limit <= bufSizeAlloc(this));
310 ASSERT(limit >= bufUsed(this));
311
312 this->pub.size = limit;
313 this->pub.sizeLimit = true;
314
315 FUNCTION_TEST_RETURN_VOID();
316 }
317
318 /**********************************************************************************************************************************/
319 void
bufUsedInc(Buffer * this,size_t inc)320 bufUsedInc(Buffer *this, size_t inc)
321 {
322 FUNCTION_TEST_BEGIN();
323 FUNCTION_TEST_PARAM(BUFFER, this);
324 FUNCTION_TEST_PARAM(SIZE, inc);
325 FUNCTION_TEST_END();
326
327 ASSERT(this != NULL);
328 ASSERT(bufUsed(this) + inc <= bufSize(this));
329
330 this->pub.used += inc;
331
332 FUNCTION_TEST_RETURN_VOID();
333 }
334
335 void
bufUsedSet(Buffer * this,size_t used)336 bufUsedSet(Buffer *this, size_t used)
337 {
338 FUNCTION_TEST_BEGIN();
339 FUNCTION_TEST_PARAM(BUFFER, this);
340 FUNCTION_TEST_PARAM(SIZE, used);
341 FUNCTION_TEST_END();
342
343 ASSERT(this != NULL);
344 ASSERT(used <= bufSize(this));
345
346 this->pub.used = used;
347
348 FUNCTION_TEST_RETURN_VOID();
349 }
350
351 void
bufUsedZero(Buffer * this)352 bufUsedZero(Buffer *this)
353 {
354 FUNCTION_TEST_BEGIN();
355 FUNCTION_TEST_PARAM(BUFFER, this);
356 FUNCTION_TEST_END();
357
358 ASSERT(this != NULL);
359
360 this->pub.used = 0;
361
362 FUNCTION_TEST_RETURN_VOID();
363 }
364
365 /**********************************************************************************************************************************/
366 String *
bufToLog(const Buffer * this)367 bufToLog(const Buffer *this)
368 {
369 String *result = strNewFmt(
370 "{used: %zu, size: %zu%s", bufUsed(this), bufSize(this),
371 bufSizeLimit(this) ? strZ(strNewFmt(", sizeAlloc: %zu}", bufSizeAlloc(this))) : "}");
372
373 return result;
374 }
375