1 /***************************************************************************
2 begin : Fri Sep 12 2003
3 copyright : (C) 2020 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * *
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 * *
23 ***************************************************************************/
24
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #define DISABLE_DEBUGLOG
31
32 #include "buffer_p.h"
33 #include <gwenhywfar/misc.h>
34 #include <gwenhywfar/debug.h>
35 #include <gwenhywfar/text.h>
36
37 #include <stdarg.h>
38 #include <stdio.h>
39
40
41
GWEN_Buffer_new(char * buffer,uint32_t size,uint32_t used,int take)42 GWEN_BUFFER *GWEN_Buffer_new(char *buffer,
43 uint32_t size,
44 uint32_t used,
45 int take)
46 {
47 GWEN_BUFFER *bf;
48
49 GWEN_NEW_OBJECT(GWEN_BUFFER, bf);
50 bf->_refCount=1;
51 if (!buffer) {
52 /* allocate buffer */
53 bf->realPtr=(char *)GWEN_Memory_malloc(size?(size+1):0);
54 assert(bf->realPtr);
55 bf->ptr=bf->realPtr;
56 bf->realBufferSize=size+1;
57 bf->bufferSize=size+1;
58 bf->flags=GWEN_BUFFER_FLAGS_OWNED;
59 bf->bytesUsed=used;
60 bf->ptr[0]=0;
61 }
62 else {
63 /* use existing buffer */
64 bf->realPtr=buffer;
65 bf->ptr=buffer;
66 bf->realBufferSize=size;
67 bf->bufferSize=size;
68 bf->bytesUsed=used;
69 if (take)
70 bf->flags=GWEN_BUFFER_FLAGS_OWNED;
71 }
72
73 bf->mode=GWEN_BUFFER_MODE_DEFAULT;
74 bf->hardLimit=GWEN_BUFFER_DEFAULT_HARDLIMIT;
75 bf->step=GWEN_BUFFER_DYNAMIC_STEP;
76 return bf;
77 }
78
79
80
GWEN_Buffer_Attach(GWEN_BUFFER * bf)81 void GWEN_Buffer_Attach(GWEN_BUFFER *bf)
82 {
83 assert(bf->_refCount);
84 bf->_refCount++;
85 }
86
87
88
GWEN_Buffer_free(GWEN_BUFFER * bf)89 void GWEN_Buffer_free(GWEN_BUFFER *bf)
90 {
91 if (bf) {
92 assert(bf->_refCount);
93 if (bf->_refCount==1) {
94 if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
95 GWEN_Memory_dealloc(bf->realPtr);
96 GWEN_FREE_OBJECT(bf);
97 }
98 else
99 bf->_refCount--;
100 }
101 }
102
103
104
GWEN_Buffer_dup(GWEN_BUFFER * bf)105 GWEN_BUFFER *GWEN_Buffer_dup(GWEN_BUFFER *bf)
106 {
107 GWEN_BUFFER *newbf;
108 uint32_t i;
109
110 GWEN_NEW_OBJECT(GWEN_BUFFER, newbf);
111 newbf->_refCount=1;
112
113 if (bf->realPtr && bf->realBufferSize) {
114 newbf->realPtr=(char *)GWEN_Memory_malloc((bf->realBufferSize)?(bf->realBufferSize+1):0);
115 newbf->ptr=newbf->realPtr+(bf->ptr-bf->realPtr);
116 newbf->realBufferSize=bf->realBufferSize;
117 newbf->bufferSize=bf->bufferSize;
118 newbf->bytesUsed=bf->bytesUsed;
119 if (newbf->bytesUsed) {
120 unsigned int toCopy;
121
122 toCopy=bf->bytesUsed+1;
123 if (toCopy>(newbf->bufferSize)) {
124 fprintf(stderr, "Panic: Too many bytes in buffer");
125 abort();
126 }
127 memmove(newbf->ptr, bf->ptr, toCopy);
128 }
129 newbf->pos=bf->pos;
130 }
131 newbf->flags=bf->flags | GWEN_BUFFER_FLAGS_OWNED;
132 newbf->mode=bf->mode&GWEN_BUFFER_MODE_COPYMASK;
133 newbf->hardLimit=bf->hardLimit;
134 newbf->step=bf->step;
135 for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++)
136 newbf->bookmarks[i]=bf->bookmarks[i];
137
138 return newbf;
139 }
140
141
142
GWEN_Buffer_Relinquish(GWEN_BUFFER * bf)143 int GWEN_Buffer_Relinquish(GWEN_BUFFER *bf)
144 {
145 assert(bf);
146 if (!(bf->flags & GWEN_BUFFER_FLAGS_OWNED))
147 return GWEN_ERROR_INVALID;
148 if (bf->realPtr!=bf->ptr)
149 return GWEN_ERROR_INVALID;
150
151 bf->flags&=~GWEN_BUFFER_FLAGS_OWNED;
152 return 0;
153 }
154
155
156
GWEN_Buffer_ReserveBytes(GWEN_BUFFER * bf,uint32_t res)157 int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, uint32_t res)
158 {
159 assert(bf);
160 if (!res)
161 return 0;
162
163 if (bf->bytesUsed) {
164 /* we need to move data */
165 if (GWEN_Buffer_AllocRoom(bf, res))
166 return -1;
167
168 memmove(bf->ptr+res, bf->ptr, bf->bytesUsed);
169 bf->ptr+=res;
170 bf->bufferSize-=res;
171 return 0;
172 }
173 else {
174 /* no data in buffer, so simply move ptrs */
175 if (GWEN_Buffer_AllocRoom(bf, res))
176 return -1;
177
178 bf->ptr+=res;
179 bf->bufferSize-=res;
180 if (bf->bufferSize)
181 bf->ptr[0]=0;
182 return 0;
183 }
184 }
185
186
187
GWEN_Buffer_GetMode(GWEN_BUFFER * bf)188 uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf)
189 {
190 assert(bf);
191 return bf->mode;
192 }
193
194
195
GWEN_Buffer_SetMode(GWEN_BUFFER * bf,uint32_t mode)196 void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
197 {
198 assert(bf);
199 bf->mode=mode;
200 }
201
202
GWEN_Buffer_AddMode(GWEN_BUFFER * bf,uint32_t mode)203 void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
204 {
205 assert(bf);
206 bf->mode|=mode;
207 }
208
209
GWEN_Buffer_SubMode(GWEN_BUFFER * bf,uint32_t mode)210 void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode)
211 {
212 assert(bf);
213 bf->mode&=~mode;
214 }
215
216
217
GWEN_Buffer_GetHardLimit(GWEN_BUFFER * bf)218 uint32_t GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf)
219 {
220 assert(bf);
221 return bf->hardLimit;
222 }
223
224
225
GWEN_Buffer_SetHardLimit(GWEN_BUFFER * bf,uint32_t l)226 void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l)
227 {
228 assert(bf);
229 assert(l);
230 bf->hardLimit=l;
231 }
232
233
234
GWEN_Buffer_GetStart(const GWEN_BUFFER * bf)235 char *GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
236 {
237 assert(bf);
238 return bf->ptr;
239 }
240
241
242
GWEN_Buffer_GetSize(const GWEN_BUFFER * bf)243 uint32_t GWEN_Buffer_GetSize(const GWEN_BUFFER *bf)
244 {
245 assert(bf);
246 if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
247 return bf->hardLimit;
248 return bf->bufferSize;
249 }
250
251
252
GWEN_Buffer_GetPos(const GWEN_BUFFER * bf)253 uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
254 {
255 assert(bf);
256 return bf->pos;
257 }
258
259
260
GWEN_Buffer_SetPos(GWEN_BUFFER * bf,uint32_t i)261 int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
262 {
263 assert(bf);
264
265 if (i>=bf->bufferSize) {
266 DBG_ERROR(GWEN_LOGDOMAIN,
267 "Position %d outside buffer boundaries (%d bytes)",
268 i, (int)(bf->bufferSize));
269 return GWEN_ERROR_BUFFER_OVERFLOW;
270 }
271 bf->pos=i;
272 return 0;
273 }
274
275
276
GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER * bf)277 uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
278 {
279 assert(bf);
280 return bf->bytesUsed;
281 }
282
283
284
GWEN_Buffer_AllocRoom(GWEN_BUFFER * bf,uint32_t size)285 int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
286 {
287 assert(bf);
288 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
289 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
290 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
291 abort();
292 }
293 return GWEN_ERROR_PERMISSIONS;
294 }
295 /*DBG_VERBOUS(GWEN_LOGDOMAIN, "Allocating %d bytes", size);*/
296 if (bf->bytesUsed+(size+1) > bf->bufferSize) {
297 /* need to realloc */
298 uint32_t nsize;
299 uint32_t noffs;
300 uint32_t reserved;
301 void *p;
302
303 /* check for dynamic mode */
304 if (!(bf->mode & GWEN_BUFFER_MODE_DYNAMIC)) {
305 DBG_ERROR(GWEN_LOGDOMAIN, "Not in dynamic mode");
306 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
307 abort();
308 }
309 return GWEN_ERROR_BUFFER_OVERFLOW;
310 }
311
312 /* calculate reserved bytes (to set ptr later) */
313 reserved=bf->ptr-bf->realPtr;
314 /* this is the raw number of bytes we need (we always add a NULL
315 * character) */
316 nsize=bf->bytesUsed+(size+1)-bf->bufferSize;
317 /* round it up */
318 nsize=(nsize+(bf->step-1));
319 nsize&=~(bf->step-1);
320 /* store number of additional bytes to allocate */
321 noffs=nsize;
322 /* add current size to it */
323 nsize+=bf->realBufferSize;
324 if (nsize>bf->hardLimit) {
325 DBG_ERROR(GWEN_LOGDOMAIN,
326 "Size is beyond hard limit (%d>%d)",
327 (int) nsize, (int)(bf->hardLimit));
328 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
329 abort();
330 }
331 return GWEN_ERROR_BUFFER_OVERFLOW;
332 }
333 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reallocating from %d to %d bytes",
334 bf->bufferSize, nsize);
335 if (bf->realPtr==NULL) {
336 p=GWEN_Memory_malloc(nsize?(nsize+1):0);
337 }
338 else {
339 p=GWEN_Memory_realloc(bf->realPtr, nsize?(nsize+1):0);
340 }
341 if (!p) {
342 DBG_ERROR(GWEN_LOGDOMAIN, "Realloc failed.");
343 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
344 abort();
345 }
346 return GWEN_ERROR_MEMORY_FULL;
347 }
348
349 /* store new size and pointer */
350 bf->realPtr=(char *)p;
351 bf->ptr=bf->realPtr+reserved;
352 bf->realBufferSize=nsize;
353 bf->bufferSize+=noffs;
354 }
355
356 return 0;
357 }
358
359
360
GWEN_Buffer_AppendBytes(GWEN_BUFFER * bf,const char * buffer,uint32_t size)361 int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf,
362 const char *buffer,
363 uint32_t size)
364 {
365 int rv;
366
367 assert(bf);
368
369 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
370 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
371 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
372 abort();
373 }
374 return GWEN_ERROR_PERMISSIONS;
375 }
376
377 rv=GWEN_Buffer_AllocRoom(bf, size+1);
378 if (rv<0) {
379 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
380 return rv;
381 }
382
383 memmove(bf->ptr+bf->bytesUsed, buffer, size);
384 if (bf->pos==bf->bytesUsed)
385 bf->pos+=size;
386 bf->bytesUsed+=size;
387 /* append a NULL to allow using the buffer as ASCIIZ string */
388 bf->ptr[bf->bytesUsed]=0;
389 return 0;
390 }
391
392
393
GWEN_Buffer_AppendByte(GWEN_BUFFER * bf,char c)394 int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
395 {
396 int rv;
397
398 assert(bf);
399
400 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
401 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
402 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
403 abort();
404 }
405 return GWEN_ERROR_PERMISSIONS;
406 }
407
408 if (bf->bytesUsed+1+1 > bf->bufferSize) {
409 rv=GWEN_Buffer_AllocRoom(bf, 1+1);
410 if (rv<0) {
411 DBG_DEBUG(GWEN_LOGDOMAIN, "here");
412 return rv;
413 }
414 }
415
416 bf->ptr[bf->bytesUsed]=c;
417 if (bf->pos == bf->bytesUsed)
418 bf->pos++;
419 /* append a NULL to allow using the buffer as ASCIIZ string */
420 bf->ptr[++(bf->bytesUsed)]=0;
421 return 0;
422 }
423
424
425
GWEN_Buffer_PeekByte(GWEN_BUFFER * bf)426 int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf)
427 {
428 assert(bf);
429
430 if (bf->pos>=bf->bytesUsed) {
431 return GWEN_ERROR_EOF;
432 }
433
434 return (unsigned char)(bf->ptr[bf->pos]);
435 }
436
437
438
GWEN_Buffer_ReadByte(GWEN_BUFFER * bf)439 int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf)
440 {
441 assert(bf);
442
443 if (bf->pos>=bf->bytesUsed) {
444 return GWEN_ERROR_EOF;
445 }
446
447 return (unsigned char)(bf->ptr[bf->pos++]);
448 }
449
450
451
GWEN_Buffer_IncrementPos(GWEN_BUFFER * bf,uint32_t i)452 int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
453 {
454 assert(bf);
455
456 if (i+bf->pos>=bf->bufferSize) {
457 DBG_DEBUG(GWEN_LOGDOMAIN,
458 "Position %d outside buffer boundaries (%d bytes)\n"
459 "Incrementing anyway",
460 i+bf->pos, bf->bufferSize);
461 }
462
463 bf->pos+=i;
464 return 0;
465 }
466
467
468
GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER * bf)469 int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
470 {
471 assert(bf);
472 if (bf->pos<=bf->bufferSize) {
473 if (bf->pos>bf->bytesUsed) {
474 DBG_DEBUG(GWEN_LOGDOMAIN, "Adjusted buffer (uses now %d bytes)",
475 bf->pos);
476 bf->bytesUsed=bf->pos;
477 }
478 /* append a NULL to allow using the buffer as ASCIIZ string */
479 bf->ptr[bf->bytesUsed]=0; /* TODO: This has to be checked (is it okay to add a byte here?)! */
480 return 0;
481 }
482 else {
483 DBG_ERROR(GWEN_LOGDOMAIN, "Pointer outside buffer size (%d bytes)",
484 (int)(bf->bufferSize));
485 return GWEN_ERROR_BUFFER_OVERFLOW;
486 }
487 }
488
489
490
GWEN_Buffer_DecrementPos(GWEN_BUFFER * bf,uint32_t i)491 int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i)
492 {
493 assert(bf);
494
495 if (bf->pos<i) {
496 DBG_ERROR(GWEN_LOGDOMAIN,
497 "Position %d outside buffer boundaries (%d bytes)",
498 bf->pos-i, bf->bufferSize);
499 return GWEN_ERROR_BUFFER_OVERFLOW;
500 }
501 bf->pos-=i;
502 return 0;
503 }
504
505
506
GWEN_Buffer_AppendBuffer(GWEN_BUFFER * bf,GWEN_BUFFER * sf)507 int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
508 {
509
510 assert(bf);
511 assert(sf);
512
513 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
514 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
515 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
516 abort();
517 }
518 return GWEN_ERROR_PERMISSIONS;
519 }
520
521 if (sf->bytesUsed)
522 return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
523 return 0;
524 }
525
526
527
GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER * bf)528 uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
529 {
530 assert(bf);
531
532 return (bf->bufferSize-(bf->bytesUsed+1));
533 }
534
535
536
GWEN_Buffer_GetBytesLeft(GWEN_BUFFER * bf)537 uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf)
538 {
539 assert(bf);
540
541 if (bf->pos<bf->bytesUsed)
542 return bf->bytesUsed-bf->pos;
543 else
544 return 0;
545 }
546
547
548
GWEN_Buffer_GetPosPointer(const GWEN_BUFFER * bf)549 char *GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
550 {
551 assert(bf);
552 return bf->ptr+bf->pos;
553 }
554
555
556
GWEN_Buffer_OverwriteContent(GWEN_BUFFER * bf,int c)557 void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c)
558 {
559 assert(bf);
560 if (bf->realPtr && bf->realBufferSize) {
561 memset(bf->realPtr, c, bf->realBufferSize);
562 }
563 }
564
565
566
GWEN_Buffer_GetBookmark(const GWEN_BUFFER * bf,unsigned int idx)567 uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
568 {
569 assert(bf);
570 assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
571 return bf->bookmarks[idx];
572 }
573
574
575
GWEN_Buffer_SetBookmark(GWEN_BUFFER * bf,unsigned int idx,uint32_t v)576 void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx,
577 uint32_t v)
578 {
579 assert(bf);
580 assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
581 bf->bookmarks[idx]=v;
582 }
583
584
585
GWEN_Buffer_Dump(GWEN_BUFFER * bf,unsigned int insert)586 void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
587 {
588 uint32_t k;
589
590 for (k=0; k<insert; k++)
591 fprintf(stderr, " ");
592 fprintf(stderr, "Buffer:\n");
593
594 for (k=0; k<insert; k++)
595 fprintf(stderr, " ");
596 fprintf(stderr, "Pos : %d (%04x)\n", bf->pos, bf->pos);
597
598 for (k=0; k<insert; k++)
599 fprintf(stderr, " ");
600 fprintf(stderr, "Buffer Size : %d\n", bf->bufferSize);
601
602 for (k=0; k<insert; k++)
603 fprintf(stderr, " ");
604 fprintf(stderr, "Hard limit : %d\n", bf->hardLimit);
605
606 for (k=0; k<insert; k++)
607 fprintf(stderr, " ");
608 fprintf(stderr, "Bytes Used : %d\n", bf->bytesUsed);
609
610 for (k=0; k<insert; k++)
611 fprintf(stderr, " ");
612 fprintf(stderr, "Bytes Reserved : %u\n",
613 (uint32_t)(bf->ptr-bf->realPtr));
614
615 for (k=0; k<insert; k++)
616 fprintf(stderr, " ");
617 fprintf(stderr, "Flags : %08x ( ", bf->flags);
618 if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
619 fprintf(stderr, "OWNED ");
620 fprintf(stderr, ")\n");
621
622 for (k=0; k<insert; k++)
623 fprintf(stderr, " ");
624 fprintf(stderr, "Mode : %08x ( ", bf->mode);
625 if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
626 fprintf(stderr, "DYNAMIC ");
627 if (bf->mode & GWEN_BUFFER_MODE_READONLY)
628 fprintf(stderr, "READONLY ");
629 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL)
630 fprintf(stderr, "ABORT_ON_MEMFULL ");
631 fprintf(stderr, ")\n");
632
633 for (k=0; k<insert; k++)
634 fprintf(stderr, " ");
635 fprintf(stderr, "Bookmarks :");
636 for (k=0; k<GWEN_BUFFER_MAX_BOOKMARKS; k++)
637 fprintf(stderr, " %d", bf->bookmarks[k]);
638 fprintf(stderr, "\n");
639
640 if (bf->ptr && bf->bytesUsed) {
641 for (k=0; k<insert; k++)
642 fprintf(stderr, " ");
643 fprintf(stderr, "Data:\n");
644 GWEN_Text_DumpString(bf->ptr, bf->bytesUsed, insert+1);
645 }
646 }
647
648
649
GWEN_Buffer_Reset(GWEN_BUFFER * bf)650 void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
651 {
652 assert(bf);
653 bf->pos=0;
654 bf->bytesUsed=0;
655 bf->ptr[0]=0;
656 }
657
658
659
GWEN_Buffer_Rewind(GWEN_BUFFER * bf)660 void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
661 {
662 assert(bf);
663 bf->pos=0;
664 }
665
666
667
GWEN_Buffer_ReadBytes(GWEN_BUFFER * bf,char * buffer,uint32_t * size)668 int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
669 {
670 /* optimized for speed */
671 uint32_t i;
672 char *pdst;
673
674 DBG_VERBOUS(GWEN_LOGDOMAIN, "About to copy up to %d bytes", *size);
675 i=0;
676 pdst=buffer;
677
678 while (i<*size) {
679 int j;
680 int srcLeft;
681
682 if (bf->pos>=bf->bytesUsed)
683 break;
684
685 srcLeft=bf->bytesUsed - bf->pos;
686 if (srcLeft==0)
687 break;
688 j=(*size)-i;
689 if (j>srcLeft)
690 j=srcLeft;
691 DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying %d bytes", j);
692 memmove(pdst, bf->ptr + bf->pos, j);
693 pdst+=j;
694 i+=j;
695 bf->pos+=j;
696 } /* while */
697
698 *size=i;
699 DBG_VERBOUS(GWEN_LOGDOMAIN, "Copied %d bytes", *size);
700 return 0;
701 }
702
703
704
GWEN_Buffer_GetStep(GWEN_BUFFER * bf)705 uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf)
706 {
707 assert(bf);
708 return bf->step;
709 }
710
711
712
GWEN_Buffer_SetStep(GWEN_BUFFER * bf,uint32_t step)713 void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
714 {
715 assert(bf);
716 bf->step=step;
717 }
718
719
720
GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER * bf,uint32_t pos,int offset)721 void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf,
722 uint32_t pos,
723 int offset)
724 {
725 uint32_t i;
726
727 assert(bf);
728 for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++) {
729 if (bf->bookmarks[i]>=pos)
730 bf->bookmarks[i]+=offset;
731 } /* for */
732 }
733
734
735
GWEN_Buffer_InsertRoom(GWEN_BUFFER * bf,uint32_t size)736 int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf,
737 uint32_t size)
738 {
739 char *p;
740 int i;
741 int rv;
742
743 assert(bf);
744
745 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
746 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
747 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
748 abort();
749 }
750 return GWEN_ERROR_PERMISSIONS;
751 }
752
753 if (bf->pos==0) {
754 if (bf->bytesUsed==0) {
755 /* no bytes used, simply return */
756 rv=GWEN_Buffer_AllocRoom(bf, size);
757 if (rv) {
758 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
759 return rv;
760 }
761 bf->bytesUsed+=size;
762 /* append "0" behind buffer */
763 bf->ptr[bf->bytesUsed]=0;
764 return 0;
765 }
766 else {
767 if ((bf->ptr - bf->realPtr) >= (int)size) {
768 /* simply occupy the reserved space */
769 bf->ptr-=size;
770 bf->bytesUsed+=size;
771 bf->bufferSize+=size;
772 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
773 return 0;
774 }
775 }
776 }
777
778 rv=GWEN_Buffer_AllocRoom(bf, size);
779 if (rv<0) {
780 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
781 return rv;
782 }
783 assert(bf->pos<=bf->bytesUsed);
784 p=bf->ptr+bf->pos;
785 i=bf->bytesUsed-bf->pos;
786 if (i>0)
787 /* move current data at pos out of the way */
788 memmove(p+size, p, i);
789 bf->bytesUsed+=size;
790 /* append "0" behind buffer */
791 bf->ptr[bf->bytesUsed]=0;
792 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
793 return 0;
794 }
795
796
797
GWEN_Buffer_RemoveRoom(GWEN_BUFFER * bf,uint32_t size)798 int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size)
799 {
800 char *p;
801 int i;
802
803 assert(bf);
804
805 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
806 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
807 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
808 abort();
809 }
810 return GWEN_ERROR_PERMISSIONS;
811 }
812
813 if (bf->bytesUsed<size+bf->pos) {
814 /* can't remove more bytes than we have */
815 return GWEN_ERROR_INVALID;
816 }
817
818 if (bf->pos==0) {
819 /* simply add to reserved space */
820 bf->ptr+=size;
821 bf->bytesUsed-=size;
822 bf->bufferSize-=size;
823 }
824 else {
825 /* we need to get the rest closer */
826 p=bf->ptr+bf->pos+size;
827 i=bf->bytesUsed-bf->pos-size;
828 memmove(bf->ptr+bf->pos, p, i);
829 bf->bytesUsed-=size;
830 }
831
832 /* append "0" behind buffer */
833 bf->ptr[bf->bytesUsed]=0;
834 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, -((int)size));
835
836 return 0;
837 }
838
839
840
GWEN_Buffer_ReplaceBytes(GWEN_BUFFER * bf,uint32_t rsize,const char * buffer,uint32_t size)841 int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf,
842 uint32_t rsize,
843 const char *buffer,
844 uint32_t size)
845 {
846 int32_t d;
847 int rv;
848
849 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
850 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
851 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
852 abort();
853 }
854 return GWEN_ERROR_PERMISSIONS;
855 }
856
857 /* either insert or remove bytes */
858 d=size-rsize;
859 if (d<0) {
860 rv=GWEN_Buffer_RemoveRoom(bf, -d);
861 }
862 else if (d>0) {
863 rv=GWEN_Buffer_InsertRoom(bf, d);
864 }
865 else
866 /* nothing to adjust if sizes are the same */
867 rv=0;
868 if (rv) {
869 DBG_ERROR(GWEN_LOGDOMAIN,
870 "Error replacing %d bytes with %d bytes (%d)",
871 rsize, size, rv);
872 return rv;
873 }
874
875 /* write new bytes */
876 if (size)
877 memmove(bf->ptr+bf->pos, buffer, size);
878 return 0;
879 }
880
881
882
GWEN_Buffer_InsertBytes(GWEN_BUFFER * bf,const char * buffer,uint32_t size)883 int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf,
884 const char *buffer,
885 uint32_t size)
886 {
887 int rv;
888
889 assert(bf);
890 assert(buffer);
891
892 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
893 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
894 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
895 abort();
896 }
897 return GWEN_ERROR_PERMISSIONS;
898 }
899
900 rv=GWEN_Buffer_InsertRoom(bf, size);
901 if (rv<0) {
902 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
903 return rv;
904 }
905 memmove(bf->ptr+bf->pos, buffer, size);
906 return 0;
907 }
908
909
910
GWEN_Buffer_InsertByte(GWEN_BUFFER * bf,char c)911 int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c)
912 {
913 int rv;
914
915 assert(bf);
916
917 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
918 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
919 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
920 abort();
921 }
922 return GWEN_ERROR_PERMISSIONS;
923 }
924
925 rv=GWEN_Buffer_InsertRoom(bf, 1);
926 if (rv<0) {
927 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
928 return rv;
929 }
930 bf->ptr[bf->pos]=c;
931 return 0;
932 }
933
934
935
GWEN_Buffer_InsertBuffer(GWEN_BUFFER * bf,GWEN_BUFFER * sf)936 int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf,
937 GWEN_BUFFER *sf)
938 {
939 assert(bf);
940 assert(sf);
941
942 return GWEN_Buffer_InsertBytes(bf, sf->ptr, sf->bytesUsed);
943 }
944
945
946
GWEN_Buffer_Crop(GWEN_BUFFER * bf,uint32_t pos,uint32_t l)947 int GWEN_Buffer_Crop(GWEN_BUFFER *bf,
948 uint32_t pos,
949 uint32_t l)
950 {
951 int offset;
952
953 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
954 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
955 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
956 abort();
957 }
958 return GWEN_ERROR_PERMISSIONS;
959 }
960
961 if (pos>=bf->bufferSize) {
962 DBG_ERROR(GWEN_LOGDOMAIN, "Position outside buffer");
963 return -1;
964 }
965 if (bf->bytesUsed-pos<l) {
966 DBG_INFO(GWEN_LOGDOMAIN, "Invalid length");
967 return -1;
968 }
969 bf->ptr+=pos;
970 bf->bufferSize-=pos;
971 if (bf->pos>pos)
972 offset=pos;
973 else
974 offset=bf->pos;
975 bf->pos-=offset;
976 bf->bytesUsed=l;
977 /* adjust position after possible truncation */
978 if (bf->pos>bf->bytesUsed)
979 bf->pos=bf->bytesUsed;
980
981 bf->ptr[bf->bytesUsed]=0;
982 GWEN_Buffer_AdjustBookmarks(bf, offset, -offset);
983
984 return 0;
985 }
986
987
988
GWEN_Buffer_AppendString(GWEN_BUFFER * bf,const char * buffer)989 int GWEN_Buffer_AppendString(GWEN_BUFFER *bf,
990 const char *buffer)
991 {
992 assert(bf);
993 assert(buffer);
994 return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
995 }
996
997
998
GWEN_Buffer_InsertString(GWEN_BUFFER * bf,const char * buffer)999 int GWEN_Buffer_InsertString(GWEN_BUFFER *bf,
1000 const char *buffer)
1001 {
1002 assert(bf);
1003 assert(buffer);
1004 return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
1005 }
1006
1007
1008
GWEN_Buffer_FillWithBytes(GWEN_BUFFER * bf,unsigned char c,uint32_t size)1009 int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf,
1010 unsigned char c,
1011 uint32_t size)
1012 {
1013 int rv;
1014
1015 assert(bf);
1016
1017 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
1018 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
1019 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
1020 abort();
1021 }
1022 return GWEN_ERROR_PERMISSIONS;
1023 }
1024
1025 rv=GWEN_Buffer_AllocRoom(bf, size+1);
1026 if (rv<0) {
1027 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
1028 return rv;
1029 }
1030 memset(bf->ptr+bf->bytesUsed, c, size);
1031 if (bf->pos==bf->bytesUsed)
1032 bf->pos+=size;
1033 bf->bytesUsed+=size;
1034 /* append a NULL to allow using the buffer as ASCIIZ string */
1035 bf->ptr[bf->bytesUsed]=0;
1036 return 0;
1037 }
1038
1039
1040
GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER * bf,unsigned char c,uint32_t size)1041 int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf,
1042 unsigned char c,
1043 uint32_t size)
1044 {
1045 int rv;
1046
1047 assert(bf);
1048
1049 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
1050 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
1051 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
1052 abort();
1053 }
1054 return GWEN_ERROR_PERMISSIONS;
1055 }
1056
1057 rv=GWEN_Buffer_InsertRoom(bf, size);
1058 if (rv<0) {
1059 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1060 return -1;
1061 }
1062 memset(bf->ptr+bf->pos, c, size);
1063 return 0;
1064 }
1065
1066
1067
GWEN_Buffer_CacheFn_Attach(void * ptr)1068 int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Attach(void *ptr)
1069 {
1070 GWEN_Buffer_Attach((GWEN_BUFFER *) ptr);
1071 return 0;
1072 }
1073
1074
1075
GWEN_Buffer_CacheFn_Free(void * ptr)1076 int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr)
1077 {
1078 GWEN_Buffer_free((GWEN_BUFFER *) ptr);
1079 return 0;
1080 }
1081
1082
1083
GWEN_Buffer_AppendArgs(GWEN_BUFFER * bf,const char * fmt,...)1084 int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt, ...)
1085 {
1086
1087 va_list list;
1088 char *p;
1089 int maxUnsegmentedWrite;
1090 int rv;
1091
1092 GWEN_Buffer_AllocRoom(bf, 256);
1093
1094 maxUnsegmentedWrite=GWEN_Buffer_GetMaxUnsegmentedWrite(bf);
1095 p=GWEN_Buffer_GetStart(bf)+GWEN_Buffer_GetPos(bf);
1096
1097 /* prepare list for va_arg */
1098 va_start(list, fmt);
1099 rv=vsnprintf(p, maxUnsegmentedWrite, fmt, list);
1100 if (rv<0) {
1101 DBG_ERROR(GWEN_LOGDOMAIN, "Error on vnsprintf (%d)", rv);
1102 va_end(list);
1103 return GWEN_ERROR_GENERIC;
1104 }
1105 else if (rv>=maxUnsegmentedWrite) {
1106 GWEN_Buffer_AllocRoom(bf, rv+1);
1107 maxUnsegmentedWrite=GWEN_Buffer_GetMaxUnsegmentedWrite(bf);
1108 p=GWEN_Buffer_GetStart(bf)+GWEN_Buffer_GetPos(bf);
1109 rv=vsnprintf(p, maxUnsegmentedWrite, fmt, list);
1110 if (rv<0) {
1111 DBG_ERROR(GWEN_LOGDOMAIN, "Error on vnsprintf (%d)", rv);
1112 va_end(list);
1113 return GWEN_ERROR_GENERIC;
1114 }
1115 }
1116 if (rv>0) {
1117 GWEN_Buffer_IncrementPos(bf, rv);
1118 GWEN_Buffer_AdjustUsedBytes(bf);
1119 }
1120 va_end(list);
1121
1122 return 0;
1123 }
1124
1125
1126
1127 #include "buffer-t.c"
1128
1129
1130
1131
1132