gwenhywfar 5.10.1
buffer.c
Go to the documentation of this file.
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
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",
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 }
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
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 }
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
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 }
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
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
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
453{
454 assert(bf);
455
456 if (i+bf->pos>=bf->bufferSize) {
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
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));
486 }
487}
488
489
490
492{
493 assert(bf);
494
495 if (bf->pos<i) {
497 "Position %d outside buffer boundaries (%d bytes)",
498 bf->pos-i, bf->bufferSize);
500 }
501 bf->pos-=i;
502 return 0;
503}
504
505
506
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 }
519 }
520
521 if (sf->bytesUsed)
522 return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
523 return 0;
524}
525
526
527
529{
530 assert(bf);
531
532 return (bf->bufferSize-(bf->bytesUsed+1));
533}
534
535
536
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
550{
551 assert(bf);
552 return bf->ptr+bf->pos;
553}
554
555
556
558{
559 assert(bf);
560 if (bf->realPtr && bf->realBufferSize) {
561 memset(bf->realPtr, c, bf->realBufferSize);
562 }
563}
564
565
566
567uint32_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
576void 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
586void 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 ");
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
651{
652 assert(bf);
653 bf->pos=0;
654 bf->bytesUsed=0;
655 bf->ptr[0]=0;
656}
657
658
659
661{
662 assert(bf);
663 bf->pos=0;
664}
665
666
667
668int 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
706{
707 assert(bf);
708 return bf->step;
709}
710
711
712
713void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
714{
715 assert(bf);
716 bf->step=step;
717}
718
719
720
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
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 }
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
798int 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 }
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
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 }
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) {
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
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 }
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
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 }
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
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
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 }
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
990 const char *buffer)
991{
992 assert(bf);
993 assert(buffer);
994 return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
995}
996
997
998
1000 const char *buffer)
1001{
1002 assert(bf);
1003 assert(buffer);
1004 return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
1005}
1006
1007
1008
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 }
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
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 }
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
1069{
1071 return 0;
1072}
1073
1074
1075
1077{
1079 return 0;
1080}
1081
1082
1083
1084int 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);
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);
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) {
1119 }
1120 va_end(list);
1121
1122 return 0;
1123}
1124
1125
1126
1128 const char *openingString,
1129 const char *closingString,
1130 int onlyBetween)
1131{
1132 const char *ptr;
1133
1134 ptr=GWEN_Text_StrCaseStr(bf->ptr, openingString);
1135 if (ptr) {
1136 int startPos=-1;
1137 int endPos=-1;
1138
1139 startPos=(ptr-bf->ptr);
1140 if (onlyBetween)
1141 startPos+=strlen(openingString);
1142 ptr+=strlen(openingString);
1143 ptr=GWEN_Text_StrCaseStr(ptr, closingString);
1144 if (ptr) {
1145 endPos=(ptr-bf->ptr);
1146 if (!onlyBetween)
1147 endPos+=strlen(closingString);
1148 }
1149
1150 if (endPos!=-1)
1151 GWEN_Buffer_Crop(bf, startPos, (endPos-startPos));
1152 else
1153 GWEN_Buffer_Crop(bf, startPos, (bf->bytesUsed-startPos)+1);
1154 return 0;
1155 }
1156 return GWEN_ERROR_NOT_FOUND;
1157}
1158
1159
1160
1161
1162
1163#include "buffer-t.c"
1164
1165
1166
1167
#define NULL
Definition: binreloc.c:300
int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:911
int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:491
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:1009
int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt,...)
Definition: buffer.c:1084
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition: buffer.c:713
int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:883
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:798
int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf, uint32_t rsize, const char *buffer, uint32_t size)
Definition: buffer.c:841
uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
Definition: buffer.c:528
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
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:469
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:537
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:586
void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l)
Definition: buffer.c:226
int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf)
Definition: buffer.c:426
void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
Definition: buffer.c:660
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:736
void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c)
Definition: buffer.c:557
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
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:999
int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition: buffer.c:507
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:439
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx, uint32_t v)
Definition: buffer.c:576
int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
Definition: buffer.c:668
int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1041
uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
Definition: buffer.c:567
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:721
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:1127
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:705
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:1068
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr)
Definition: buffer.c:1076
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition: buffer.c:947
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:936
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
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_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#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
Definition: gwenhywfarapi.h:89
#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