gwenhywfar  5.14.1
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 
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 
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);
96  GWEN_FREE_OBJECT(bf);
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 
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 
189 {
190  assert(bf);
191  return bf->mode;
192 }
193 
194 
195 
196 void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
197 {
198  assert(bf);
199  bf->mode=mode;
200 }
201 
202 
203 void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
204 {
205  assert(bf);
206  bf->mode|=mode;
207 }
208 
209 
210 void 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 
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 
253 uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
254 {
255  assert(bf);
256  return bf->pos;
257 }
258 
259 
260 
261 int 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 
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  }
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  }
345  return GWEN_ERROR_MEMORY_FULL;
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  }
373  return GWEN_ERROR_PERMISSIONS;
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  }
404  return GWEN_ERROR_PERMISSIONS;
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  }
517  return GWEN_ERROR_PERMISSIONS;
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 
566 uint32_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 
575 void 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 
585 void 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 ");
632  if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL)
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 
671 int 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 
716 void 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  }
753  return GWEN_ERROR_PERMISSIONS;
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 
801 int 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  }
813  return GWEN_ERROR_PERMISSIONS;
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  }
857  return GWEN_ERROR_PERMISSIONS;
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  }
900  return GWEN_ERROR_PERMISSIONS;
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  }
925  return GWEN_ERROR_PERMISSIONS;
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  }
961  return GWEN_ERROR_PERMISSIONS;
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  }
1025  return GWEN_ERROR_PERMISSIONS;
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  }
1057  return GWEN_ERROR_PERMISSIONS;
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 {
1081  GWEN_Buffer_free((GWEN_BUFFER *) ptr);
1082  return 0;
1083 }
1084 
1085 
1086 
1087 int 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) {
1121  GWEN_Buffer_IncrementPos(bf, rv);
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 
GWENHYWFAR_API const char * fmt
Definition: buffer.h:283
uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf)
Definition: buffer.c:536
#define DBG_ERROR(dbg_logger, format,...)
Definition: debug.h:97
int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1044
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_InsertString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1002
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:285
uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf)
Definition: buffer.c:527
#define GWEN_ERROR_INVALID
Definition: error.h:67
#define DBG_DEBUG(dbg_logger, format,...)
Definition: debug.h:214
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l)
Definition: buffer.c:226
void GWEN_Text_DumpString(const char *s, unsigned int l, unsigned int insert)
Definition: text.c:1283
int GWEN_Buffer_KeepTextBetweenStrings(GWEN_BUFFER *bf, const char *openingString, const char *closingString, int onlyBetween)
Definition: buffer.c:1130
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition: buffer.c:716
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
void GWEN_Memory_dealloc(void *p)
Definition: memory.c:69
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:468
#define GWEN_LOGDOMAIN
Definition: logger.h:32
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition: buffer.c:253
#define DBG_VERBOUS(dbg_logger, format,...)
Definition: debug.h:224
int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, uint32_t res)
Definition: buffer.c:157
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
#define GWEN_ERROR_BUFFER_OVERFLOW
Definition: error.h:79
int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:801
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:585
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:548
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:653
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr)
Definition: buffer.c:1079
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:451
void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx, uint32_t v)
Definition: buffer.c:575
void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf, uint32_t pos, int offset)
Definition: buffer.c:724
int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf)
Definition: buffer.c:425
uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
Definition: buffer.c:566
void GWEN_Buffer_Attach(GWEN_BUFFER *bf)
Definition: buffer.c:81
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
uint32_t GWEN_Buffer_GetSize(const GWEN_BUFFER *bf)
Definition: buffer.c:243
void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:210
#define GWENHYWFAR_CB
Definition: gwenhywfarapi.h:89
int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition: buffer.c:506
int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:914
const char * GWEN_Text_StrCaseStr(const char *haystack, const char *needle)
Definition: text.c:1083
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Attach(void *ptr)
Definition: buffer.c:1071
void * GWEN_Memory_malloc(size_t wsize)
Definition: memory.c:39
int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt,...)
Definition: buffer.c:1087
#define GWEN_ERROR_GENERIC
Definition: error.h:62
#define GWEN_BUFFER_MODE_DYNAMIC
Definition: buffer.h:66
void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:203
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:393
#define GWEN_ERROR_PERMISSIONS
Definition: error.h:126
int GWEN_Buffer_Relinquish(GWEN_BUFFER *bf)
Definition: buffer.c:143
GWEN_BUFFER * GWEN_Buffer_dup(GWEN_BUFFER *bf)
Definition: buffer.c:105
int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:490
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition: buffer.c:950
void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:196
uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf)
Definition: buffer.c:708
#define GWEN_ERROR_EOF
Definition: error.h:96
int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:261
#define GWEN_BUFFER_MODE_ABORT_ON_MEMFULL
Definition: buffer.h:67
#define GWEN_BUFFER_MAX_BOOKMARKS
Definition: buffer.h:64
int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition: buffer.c:939
#define GWEN_ERROR_NOT_FOUND
Definition: error.h:89
uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf)
Definition: buffer.c:188
int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf)
Definition: buffer.c:438
int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1012
#define GWEN_BUFFER_MODE_READONLY
Definition: buffer.h:68
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:360
void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
Definition: buffer.c:663
void * GWEN_Memory_realloc(void *oldp, size_t nsize)
Definition: memory.c:59
int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:739
#define DBG_INFO(dbg_logger, format,...)
Definition: debug.h:181
int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:886
uint32_t GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf)
Definition: buffer.c:218
int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf, uint32_t rsize, const char *buffer, uint32_t size)
Definition: buffer.c:844
int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
Definition: buffer.c:671
#define GWEN_ERROR_MEMORY_FULL
Definition: error.h:77
#define GWEN_BUFFER_MODE_DEFAULT
Definition: buffer.h:70
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:992
void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c)
Definition: buffer.c:556