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