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