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 
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",
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 
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 
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 
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  }
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 
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 
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 
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 
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 
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 
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 
706 {
707  assert(bf);
708  return bf->step;
709 }
710 
711 
712 
713 void 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  }
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 
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 
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) {
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  }
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 
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 
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  }
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 
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  }
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 
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 
1069 {
1071  return 0;
1072 }
1073 
1074 
1075 
1077 {
1078  GWEN_Buffer_free((GWEN_BUFFER *) ptr);
1079  return 0;
1080 }
1081 
1082 
1083 
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);
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) {
1117  GWEN_Buffer_IncrementPos(bf, rv);
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 
GWENHYWFAR_API const char * fmt
Definition: buffer.h:283
uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf)
Definition: buffer.c:537
int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1041
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:999
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:528
#define GWEN_ERROR_INVALID
Definition: error.h:67
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:1127
void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step)
Definition: buffer.c:713
#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
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
#define GWEN_LOGDOMAIN
Definition: logger.h:35
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition: buffer.c:253
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:798
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:586
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
int GWENHYWFAR_CB GWEN_Buffer_CacheFn_Free(void *ptr)
Definition: buffer.c:1076
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx, uint32_t v)
Definition: buffer.c:576
void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf, uint32_t pos, int offset)
Definition: buffer.c:721
int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf)
Definition: buffer.c:426
uint32_t GWEN_Buffer_GetBookmark(const GWEN_BUFFER *bf, unsigned int idx)
Definition: buffer.c:567
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
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf, GWEN_BUFFER *sf)
Definition: buffer.c:507
int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:911
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:1068
void * GWEN_Memory_malloc(size_t wsize)
Definition: memory.c:39
int GWEN_Buffer_AppendArgs(GWEN_BUFFER *bf, const char *fmt,...)
Definition: buffer.c:1084
#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:394
#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:491
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:947
void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode)
Definition: buffer.c:196
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf)
Definition: buffer.c:705
#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:936
#define GWEN_ERROR_NOT_FOUND
Definition: error.h:89
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf)
Definition: buffer.c:188
int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf)
Definition: buffer.c:439
int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf, unsigned char c, uint32_t size)
Definition: buffer.c:1009
#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:361
void GWEN_Buffer_Rewind(GWEN_BUFFER *bf)
Definition: buffer.c:660
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:736
int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:883
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:841
int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf, char *buffer, uint32_t *size)
Definition: buffer.c:668
#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:989
void GWEN_Buffer_OverwriteContent(GWEN_BUFFER *bf, int c)
Definition: buffer.c:557