gwenhywfar 5.12.0
buffer.c
Go to the documentation of this file.
1/***************************************************************************
2 begin : Fri Sep 12 2003
3 copyright : (C) 2024 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
43 uint32_t size,
44 uint32_t used,
45 int take)
46{
47 GWEN_BUFFER *bf;
48
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
74 bf->hardLimit=GWEN_BUFFER_DEFAULT_HARDLIMIT;
75 bf->step=GWEN_BUFFER_DYNAMIC_STEP;
76 return bf;
77}
78
79
80
82{
83 assert(bf->_refCount);
84 bf->_refCount++;
85}
86
87
88
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);
97 }
98 else
99 bf->_refCount--;
100 }
101}
102
103
104
106{
107 GWEN_BUFFER *newbf;
108 uint32_t i;
109
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
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
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
189{
190 assert(bf);
191 return bf->mode;
192}
193
194
195
196void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
197{
198 assert(bf);
199 bf->mode=mode;
200}
201
202
203void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
204{
205 assert(bf);
206 bf->mode|=mode;
207}
208
209
210void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode)
211{
212 assert(bf);
213 bf->mode&=~mode;
214}
215
216
217
219{
220 assert(bf);
221 return bf->hardLimit;
222}
223
224
225
227{
228 assert(bf);
229 assert(l);
230 bf->hardLimit=l;
231}
232
233
234
236{
237 assert(bf);
238 return bf->ptr;
239}
240
241
242
244{
245 assert(bf);
246 if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
247 return bf->hardLimit;
248 return bf->bufferSize;
249}
250
251
252
254{
255 assert(bf);
256 return bf->pos;
257}
258
259
260
261int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
262{
263 assert(bf);
264
265 if (i>=bf->bufferSize) {
267 "Position %d outside buffer boundaries (%d bytes)",
268 i, (int)(bf->bufferSize));
270 }
271 bf->pos=i;
272 return 0;
273}
274
275
276
278{
279 assert(bf);
280 return bf->bytesUsed;
281}
282
283
284
285int 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 }
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 }
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) {
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 }
332 }
333 /*DBG_VERBOUS(GWEN_LOGDOMAIN, "Reallocating from %d to %d bytes", bf->bufferSize, nsize);*/
334 if (bf->realPtr==NULL) {
335 p=GWEN_Memory_malloc(nsize?(nsize+1):0);
336 }
337 else {
338 p=GWEN_Memory_realloc(bf->realPtr, nsize?(nsize+1):0);
339 }
340 if (!p) {
341 DBG_ERROR(GWEN_LOGDOMAIN, "Realloc failed.");
342 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
343 abort();
344 }
346 }
347
348 /* store new size and pointer */
349 bf->realPtr=(char *)p;
350 bf->ptr=bf->realPtr+reserved;
351 bf->realBufferSize=nsize;
352 bf->bufferSize+=noffs;
353 }
354
355 return 0;
356}
357
358
359
361 const char *buffer,
362 uint32_t size)
363{
364 int rv;
365
366 assert(bf);
367
368 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
369 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
370 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
371 abort();
372 }
374 }
375
376 rv=GWEN_Buffer_AllocRoom(bf, size+1);
377 if (rv<0) {
378 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
379 return rv;
380 }
381
382 memmove(bf->ptr+bf->bytesUsed, buffer, size);
383 if (bf->pos==bf->bytesUsed)
384 bf->pos+=size;
385 bf->bytesUsed+=size;
386 /* append a NULL to allow using the buffer as ASCIIZ string */
387 bf->ptr[bf->bytesUsed]=0;
388 return 0;
389}
390
391
392
394{
395 int rv;
396
397 assert(bf);
398
399 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
400 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
401 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
402 abort();
403 }
405 }
406
407 if (bf->bytesUsed+1+1 > bf->bufferSize) {
408 rv=GWEN_Buffer_AllocRoom(bf, 1+1);
409 if (rv<0) {
410 DBG_DEBUG(GWEN_LOGDOMAIN, "here");
411 return rv;
412 }
413 }
414
415 bf->ptr[bf->bytesUsed]=c;
416 if (bf->pos == bf->bytesUsed)
417 bf->pos++;
418 /* append a NULL to allow using the buffer as ASCIIZ string */
419 bf->ptr[++(bf->bytesUsed)]=0;
420 return 0;
421}
422
423
424
426{
427 assert(bf);
428
429 if (bf->pos>=bf->bytesUsed) {
430 return GWEN_ERROR_EOF;
431 }
432
433 return (unsigned char)(bf->ptr[bf->pos]);
434}
435
436
437
439{
440 assert(bf);
441
442 if (bf->pos>=bf->bytesUsed) {
443 return GWEN_ERROR_EOF;
444 }
445
446 return (unsigned char)(bf->ptr[bf->pos++]);
447}
448
449
450
452{
453 assert(bf);
454
455 if (i+bf->pos>=bf->bufferSize) {
457 "Position %d outside buffer boundaries (%d bytes)\n"
458 "Incrementing anyway",
459 i+bf->pos, bf->bufferSize);
460 }
461
462 bf->pos+=i;
463 return 0;
464}
465
466
467
469{
470 assert(bf);
471 if (bf->pos<=bf->bufferSize) {
472 if (bf->pos>bf->bytesUsed) {
473 DBG_DEBUG(GWEN_LOGDOMAIN, "Adjusted buffer (uses now %d bytes)",
474 bf->pos);
475 bf->bytesUsed=bf->pos;
476 }
477 /* append a NULL to allow using the buffer as ASCIIZ string */
478 bf->ptr[bf->bytesUsed]=0; /* TODO: This has to be checked (is it okay to add a byte here?)! */
479 return 0;
480 }
481 else {
482 DBG_ERROR(GWEN_LOGDOMAIN, "Pointer outside buffer size (%d bytes)",
483 (int)(bf->bufferSize));
485 }
486}
487
488
489
491{
492 assert(bf);
493
494 if (bf->pos<i) {
496 "Position %d outside buffer boundaries (%d bytes)",
497 bf->pos-i, bf->bufferSize);
499 }
500 bf->pos-=i;
501 return 0;
502}
503
504
505
507{
508
509 assert(bf);
510 assert(sf);
511
512 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
513 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
514 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
515 abort();
516 }
518 }
519
520 if (sf->bytesUsed)
521 return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
522 return 0;
523}
524
525
526
528{
529 assert(bf);
530
531 return (bf->bufferSize-(bf->bytesUsed+1));
532}
533
534
535
537{
538 assert(bf);
539
540 if (bf->pos<bf->bytesUsed)
541 return bf->bytesUsed-bf->pos;
542 else
543 return 0;
544}
545
546
547
549{
550 assert(bf);
551 return bf->ptr+bf->pos;
552}
553
554
555
557{
558 assert(bf);
559 if (bf->realPtr && bf->realBufferSize) {
560 memset(bf->realPtr, c, bf->realBufferSize);
561 }
562}
563
564
565
566uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
567{
568 assert(bf);
569 assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
570 return bf->bookmarks[idx];
571}
572
573
574
575void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx,
576 uint32_t v)
577{
578 assert(bf);
579 assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
580 bf->bookmarks[idx]=v;
581}
582
583
584
585void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
586{
587 uint32_t k;
588
589 for (k=0; k<insert; k++)
590 fprintf(stderr, " ");
591 fprintf(stderr, "Buffer:\n");
592
593 for (k=0; k<insert; k++)
594 fprintf(stderr, " ");
595 fprintf(stderr, "Pos : %d (%04x)\n", bf->pos, bf->pos);
596
597 for (k=0; k<insert; k++)
598 fprintf(stderr, " ");
599 fprintf(stderr, "Buffer Size : %d\n", bf->bufferSize);
600
601 for (k=0; k<insert; k++)
602 fprintf(stderr, " ");
603 fprintf(stderr, "Real Buffer Size : %d\n", bf->realBufferSize);
604
605 for (k=0; k<insert; k++)
606 fprintf(stderr, " ");
607 fprintf(stderr, "Hard limit : %d\n", bf->hardLimit);
608
609 for (k=0; k<insert; k++)
610 fprintf(stderr, " ");
611 fprintf(stderr, "Bytes Used : %d\n", bf->bytesUsed);
612
613 for (k=0; k<insert; k++)
614 fprintf(stderr, " ");
615 fprintf(stderr, "Bytes Reserved : %u\n",
616 (uint32_t)(bf->ptr-bf->realPtr));
617
618 for (k=0; k<insert; k++)
619 fprintf(stderr, " ");
620 fprintf(stderr, "Flags : %08x ( ", bf->flags);
621 if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
622 fprintf(stderr, "OWNED ");
623 fprintf(stderr, ")\n");
624
625 for (k=0; k<insert; k++)
626 fprintf(stderr, " ");
627 fprintf(stderr, "Mode : %08x ( ", bf->mode);
628 if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
629 fprintf(stderr, "DYNAMIC ");
630 if (bf->mode & GWEN_BUFFER_MODE_READONLY)
631 fprintf(stderr, "READONLY ");
633 fprintf(stderr, "ABORT_ON_MEMFULL ");
634 fprintf(stderr, ")\n");
635
636 for (k=0; k<insert; k++)
637 fprintf(stderr, " ");
638 fprintf(stderr, "Bookmarks :");
639 for (k=0; k<GWEN_BUFFER_MAX_BOOKMARKS; k++)
640 fprintf(stderr, " %d", bf->bookmarks[k]);
641 fprintf(stderr, "\n");
642
643 if (bf->ptr && bf->bytesUsed) {
644 for (k=0; k<insert; k++)
645 fprintf(stderr, " ");
646 fprintf(stderr, "Data:\n");
647 GWEN_Text_DumpString(bf->ptr, bf->bytesUsed, insert+1);
648 }
649}
650
651
652
654{
655 assert(bf);
656 bf->pos=0;
657 bf->bytesUsed=0;
658 bf->ptr[0]=0;
659}
660
661
662
664{
665 assert(bf);
666 bf->pos=0;
667}
668
669
670
671int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
672{
673 /* optimized for speed */
674 uint32_t i;
675 char *pdst;
676
677 DBG_VERBOUS(GWEN_LOGDOMAIN, "About to copy up to %d bytes", *size);
678 i=0;
679 pdst=buffer;
680
681 while (i<*size) {
682 int j;
683 int srcLeft;
684
685 if (bf->pos>=bf->bytesUsed)
686 break;
687
688 srcLeft=bf->bytesUsed - bf->pos;
689 if (srcLeft==0)
690 break;
691 j=(*size)-i;
692 if (j>srcLeft)
693 j=srcLeft;
694 DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying %d bytes", j);
695 memmove(pdst, bf->ptr + bf->pos, j);
696 pdst+=j;
697 i+=j;
698 bf->pos+=j;
699 } /* while */
700
701 *size=i;
702 DBG_VERBOUS(GWEN_LOGDOMAIN, "Copied %d bytes", *size);
703 return 0;
704}
705
706
707
709{
710 assert(bf);
711 return bf->step;
712}
713
714
715
716void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
717{
718 assert(bf);
719 bf->step=step;
720}
721
722
723
725 uint32_t pos,
726 int offset)
727{
728 uint32_t i;
729
730 assert(bf);
731 for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++) {
732 if (bf->bookmarks[i]>=pos)
733 bf->bookmarks[i]+=offset;
734 } /* for */
735}
736
737
738
740 uint32_t size)
741{
742 char *p;
743 int i;
744 int rv;
745
746 assert(bf);
747
748 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
749 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
750 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
751 abort();
752 }
754 }
755
756 if (bf->pos==0) {
757 if (bf->bytesUsed==0) {
758 /* no bytes used, simply return */
759 rv=GWEN_Buffer_AllocRoom(bf, size);
760 if (rv) {
761 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
762 return rv;
763 }
764 bf->bytesUsed+=size;
765 /* append "0" behind buffer */
766 bf->ptr[bf->bytesUsed]=0;
767 return 0;
768 }
769 else {
770 if ((bf->ptr - bf->realPtr) >= (int)size) {
771 /* simply occupy the reserved space */
772 bf->ptr-=size;
773 bf->bytesUsed+=size;
774 bf->bufferSize+=size;
775 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
776 return 0;
777 }
778 }
779 }
780
781 rv=GWEN_Buffer_AllocRoom(bf, size);
782 if (rv<0) {
783 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
784 return rv;
785 }
786 assert(bf->pos<=bf->bytesUsed);
787 p=bf->ptr+bf->pos;
788 i=bf->bytesUsed-bf->pos;
789 if (i>0)
790 /* move current data at pos out of the way */
791 memmove(p+size, p, i);
792 bf->bytesUsed+=size;
793 /* append "0" behind buffer */
794 bf->ptr[bf->bytesUsed]=0;
795 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
796 return 0;
797}
798
799
800
801int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size)
802{
803 char *p;
804 int i;
805
806 assert(bf);
807
808 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
809 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
810 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
811 abort();
812 }
814 }
815
816 if (bf->bytesUsed<size+bf->pos) {
817 /* can't remove more bytes than we have */
818 return GWEN_ERROR_INVALID;
819 }
820
821 if (bf->pos==0) {
822 /* simply add to reserved space */
823 bf->ptr+=size;
824 bf->bytesUsed-=size;
825 bf->bufferSize-=size;
826 }
827 else {
828 /* we need to get the rest closer */
829 p=bf->ptr+bf->pos+size;
830 i=bf->bytesUsed-bf->pos-size;
831 memmove(bf->ptr+bf->pos, p, i);
832 bf->bytesUsed-=size;
833 }
834
835 /* append "0" behind buffer */
836 bf->ptr[bf->bytesUsed]=0;
837 GWEN_Buffer_AdjustBookmarks(bf, bf->pos, -((int)size));
838
839 return 0;
840}
841
842
843
845 uint32_t rsize,
846 const char *buffer,
847 uint32_t size)
848{
849 int32_t d;
850 int rv;
851
852 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
853 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
854 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
855 abort();
856 }
858 }
859
860 /* either insert or remove bytes */
861 d=size-rsize;
862 if (d<0) {
863 rv=GWEN_Buffer_RemoveRoom(bf, -d);
864 }
865 else if (d>0) {
866 rv=GWEN_Buffer_InsertRoom(bf, d);
867 }
868 else
869 /* nothing to adjust if sizes are the same */
870 rv=0;
871 if (rv) {
873 "Error replacing %d bytes with %d bytes (%d)",
874 rsize, size, rv);
875 return rv;
876 }
877
878 /* write new bytes */
879 if (size)
880 memmove(bf->ptr+bf->pos, buffer, size);
881 return 0;
882}
883
884
885
887 const char *buffer,
888 uint32_t size)
889{
890 int rv;
891
892 assert(bf);
893 assert(buffer);
894
895 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
896 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
897 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
898 abort();
899 }
901 }
902
903 rv=GWEN_Buffer_InsertRoom(bf, size);
904 if (rv<0) {
905 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
906 return rv;
907 }
908 memmove(bf->ptr+bf->pos, buffer, size);
909 return 0;
910}
911
912
913
915{
916 int rv;
917
918 assert(bf);
919
920 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
921 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
922 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
923 abort();
924 }
926 }
927
928 rv=GWEN_Buffer_InsertRoom(bf, 1);
929 if (rv<0) {
930 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
931 return rv;
932 }
933 bf->ptr[bf->pos]=c;
934 return 0;
935}
936
937
938
940 GWEN_BUFFER *sf)
941{
942 assert(bf);
943 assert(sf);
944
945 return GWEN_Buffer_InsertBytes(bf, sf->ptr, sf->bytesUsed);
946}
947
948
949
951 uint32_t pos,
952 uint32_t l)
953{
954 int offset;
955
956 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
957 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
958 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
959 abort();
960 }
962 }
963
964 if (pos>=bf->bufferSize) {
965 DBG_ERROR(GWEN_LOGDOMAIN, "Position outside buffer");
966 return -1;
967 }
968 if (bf->bytesUsed-pos<l) {
969 DBG_INFO(GWEN_LOGDOMAIN, "Invalid length");
970 return -1;
971 }
972 bf->ptr+=pos;
973 bf->bufferSize-=pos;
974 if (bf->pos>pos)
975 offset=pos;
976 else
977 offset=bf->pos;
978 bf->pos-=offset;
979 bf->bytesUsed=l;
980 /* adjust position after possible truncation */
981 if (bf->pos>bf->bytesUsed)
982 bf->pos=bf->bytesUsed;
983
984 bf->ptr[bf->bytesUsed]=0;
985 GWEN_Buffer_AdjustBookmarks(bf, offset, -offset);
986
987 return 0;
988}
989
990
991
993 const char *buffer)
994{
995 assert(bf);
996 assert(buffer);
997 return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
998}
999
1000
1001
1003 const char *buffer)
1004{
1005 assert(bf);
1006 assert(buffer);
1007 return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
1008}
1009
1010
1011
1013 unsigned char c,
1014 uint32_t size)
1015{
1016 int rv;
1017
1018 assert(bf);
1019
1020 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
1021 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
1022 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
1023 abort();
1024 }
1026 }
1027
1028 rv=GWEN_Buffer_AllocRoom(bf, size+1);
1029 if (rv<0) {
1030 DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
1031 return rv;
1032 }
1033 memset(bf->ptr+bf->bytesUsed, c, size);
1034 if (bf->pos==bf->bytesUsed)
1035 bf->pos+=size;
1036 bf->bytesUsed+=size;
1037 /* append a NULL to allow using the buffer as ASCIIZ string */
1038 bf->ptr[bf->bytesUsed]=0;
1039 return 0;
1040}
1041
1042
1043
1045 unsigned char c,
1046 uint32_t size)
1047{
1048 int rv;
1049
1050 assert(bf);
1051
1052 if (bf->mode & GWEN_BUFFER_MODE_READONLY) {
1053 DBG_ERROR(GWEN_LOGDOMAIN, "Read-only mode");
1054 if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
1055 abort();
1056 }
1058 }
1059
1060 rv=GWEN_Buffer_InsertRoom(bf, size);
1061 if (rv<0) {
1062 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1063 return -1;
1064 }
1065 memset(bf->ptr+bf->pos, c, size);
1066 return 0;
1067}
1068
1069
1070
1072{
1074 return 0;
1075}
1076
1077
1078
1080{
1082 return 0;
1083}
1084
1085
1086
1087int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt, ...)
1088{
1089
1090 va_list list;
1091 char *p;
1092 int maxUnsegmentedWrite;
1093 int rv;
1094
1095 GWEN_Buffer_AllocRoom(bf, 256);
1096
1097 maxUnsegmentedWrite=GWEN_Buffer_GetMaxUnsegmentedWrite(bf);
1099
1100 /* prepare list for va_arg */
1101 va_start(list, fmt);
1102 rv=vsnprintf(p, maxUnsegmentedWrite, fmt, list);
1103 va_end(list);
1104 if (rv<0) {
1105 DBG_ERROR(GWEN_LOGDOMAIN, "Error on vnsprintf (%d)", rv);
1106 return GWEN_ERROR_GENERIC;
1107 }
1108 else if (rv>=maxUnsegmentedWrite) {
1109 GWEN_Buffer_AllocRoom(bf, rv+1);
1110 maxUnsegmentedWrite=GWEN_Buffer_GetMaxUnsegmentedWrite(bf);
1112 va_start(list, fmt);
1113 rv=vsnprintf(p, maxUnsegmentedWrite, fmt, list);
1114 va_end(list);
1115 if (rv<0) {
1116 DBG_ERROR(GWEN_LOGDOMAIN, "Error on vnsprintf (%d)", rv);
1117 return GWEN_ERROR_GENERIC;
1118 }
1119 }
1120 if (rv>0) {
1123 }
1124
1125 return 0;
1126}
1127
1128
1129
1131 const char *openingString,
1132 const char *closingString,
1133 int onlyBetween)
1134{
1135 const char *ptr;
1136
1137 ptr=GWEN_Text_StrCaseStr(bf->ptr, openingString);
1138 if (ptr) {
1139 int startPos=-1;
1140 int endPos=-1;
1141
1142 startPos=(ptr-bf->ptr);
1143 if (onlyBetween)
1144 startPos+=strlen(openingString);
1145 ptr+=strlen(openingString);
1146 ptr=GWEN_Text_StrCaseStr(ptr, closingString);
1147 if (ptr) {
1148 endPos=(ptr-bf->ptr);
1149 if (!onlyBetween)
1150 endPos+=strlen(closingString);
1151 }
1152
1153 if (endPos!=-1)
1154 GWEN_Buffer_Crop(bf, startPos, (endPos-startPos));
1155 else
1156 GWEN_Buffer_Crop(bf, startPos, (bf->bytesUsed-startPos)+1);
1157 return 0;
1158 }
1159 return GWEN_ERROR_NOT_FOUND;
1160}
1161
1162
1163
1164
1165
1166#include "buffer-t.c"
1167
1168
1169
1170
#define NULL
Definition binreloc.c:300
int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c)
Definition buffer.c:914
int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition buffer.c:490
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition buffer.c:42
int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition buffer.c:1012
int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt,...)
Definition buffer.c:1087
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition buffer.c:716
int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition buffer.c:886
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition buffer.c:451
int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size)
Definition buffer.c:801
int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf, uint32_t rsize, const char *buffer, uint32_t size)
Definition buffer.c:844
uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
Definition buffer.c:527
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition buffer.c:653
int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
Definition buffer.c:261
GWEN_BUFFER * GWEN_Buffer_dup(GWEN_BUFFER *bf)
Definition buffer.c:105
uint32_t GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf)
Definition buffer.c:218
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition buffer.c:468
void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode)
Definition buffer.c:210
uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf)
Definition buffer.c:536
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition buffer.c:585
void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l)
Definition buffer.c:226
int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf)
Definition buffer.c:425
void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
Definition buffer.c:663
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition buffer.c:548
int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf, uint32_t size)
Definition buffer.c:739
void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c)
Definition buffer.c:556
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition buffer.c:360
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition buffer.c:253
uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf)
Definition buffer.c:188
int GWEN_Buffer_InsertString(GWEN_BUFFER *bf, const char *buffer)
Definition buffer.c:1002
int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition buffer.c:506
void GWEN_Buffer_Attach(GWEN_BUFFER *bf)
Definition buffer.c:81
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition buffer.c:89
int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf)
Definition buffer.c:438
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition buffer.c:992
void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx, uint32_t v)
Definition buffer.c:575
int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
Definition buffer.c:671
int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition buffer.c:1044
uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
Definition buffer.c:566
int GWEN_Buffer_Relinquish(GWEN_BUFFER *bf)
Definition buffer.c:143
void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf, uint32_t pos, int offset)
Definition buffer.c:724
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition buffer.c:277
int GWEN_Buffer_KeepTextBetweenStrings(GWEN_BUFFER *bf, const char *openingString, const char *closingString, int onlyBetween)
Definition buffer.c:1130
uint32_t GWEN_Buffer_GetSize(const GWEN_BUFFER *bf)
Definition buffer.c:243
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition buffer.c:235
uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf)
Definition buffer.c:708
void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
Definition buffer.c:203
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition buffer.c:285
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Attach(void *ptr)
Definition buffer.c:1071
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr)
Definition buffer.c:1079
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition buffer.c:950
int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, uint32_t res)
Definition buffer.c:157
int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition buffer.c:939
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition buffer.c:393
void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
Definition buffer.c:196
#define GWEN_BUFFER_MAX_BOOKMARKS
Definition buffer.h:64
#define GWEN_BUFFER_MODE_ABORT_ON_MEMFULL
Definition buffer.h:67
#define GWEN_BUFFER_MODE_DYNAMIC
Definition buffer.h:66
#define GWEN_BUFFER_MODE_READONLY
Definition buffer.h:68
GWENHYWFAR_API const char * fmt
Definition buffer.h:283
#define GWEN_BUFFER_MODE_DEFAULT
Definition buffer.h:70
#define DBG_VERBOUS(dbg_logger, format,...)
Definition debug.h:224
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define DBG_ERROR(dbg_logger, format,...)
Definition debug.h:97
#define DBG_DEBUG(dbg_logger, format,...)
Definition debug.h:214
#define GWEN_ERROR_MEMORY_FULL
Definition error.h:77
#define GWEN_ERROR_INVALID
Definition error.h:67
#define GWEN_ERROR_BUFFER_OVERFLOW
Definition error.h:79
#define GWEN_ERROR_PERMISSIONS
Definition error.h:126
#define GWEN_ERROR_GENERIC
Definition error.h:62
#define GWEN_ERROR_NOT_FOUND
Definition error.h:89
#define GWEN_ERROR_EOF
Definition error.h:96
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition buffer.h:38
#define GWENHYWFAR_CB
#define GWEN_LOGDOMAIN
Definition logger.h:35
void * GWEN_Memory_realloc(void *oldp, size_t nsize)
Definition memory.c:59
void * GWEN_Memory_malloc(size_t wsize)
Definition memory.c:39
void GWEN_Memory_dealloc(void *p)
Definition memory.c:69
#define GWEN_FREE_OBJECT(varname)
Definition memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition memory.h:55
const char * GWEN_Text_StrCaseStr(const char *haystack, const char *needle)
Definition text.c:1083
void GWEN_Text_DumpString(const char *s, unsigned int l, unsigned int insert)
Definition text.c:1283