1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#include "bytebuffer.h"
10#include "debug.h"
11
12#ifndef TRUE
13#define TRUE 1
14#endif
15#ifndef FALSE
16#define FALSE 0
17#endif
18
19#define DEFAULTALLOC 1024
20#define ALLOCINCR 1024
21
22int bbdebug = 1;
23
24/* For debugging purposes*/
25static long
26bbFail(void)
27{
28    fflush(stdout);
29    fprintf(stderr,"bytebuffer failure\n");
30    fflush(stderr);
31    if(bbdebug) exit(1);
32    return FALSE;
33}
34
35Bytebuffer*
36bbNew(void)
37{
38  Bytebufferbb = (Bytebuffer*)emalloc(sizeof(Bytebuffer));
39  if(bb == NULL) return (Bytebuffer*)bbFail();
40  bb->alloc=0;
41  bb->length=0;
42  bb->content=NULL;
43  bb->nonextendible = 0;
44  return bb;
45}
46
47int
48bbSetalloc(Bytebufferbb, const unsigned int sz0)
49{
50  unsigned int sz = sz0;
51  char* newcontent;
52  if(bb == NULL) return bbFail();
53  if(sz <= 0) {sz = (bb->alloc?2*bb->alloc:DEFAULTALLOC);}
54  else if(bb->alloc >= sz) return TRUE;
55  else if(bb->nonextendible) return bbFail();
56  newcontent=(char*)ecalloc(sz,sizeof(char));
57  if(bb->alloc > 0 && bb->length > 0 && bb->content != NULL) {
58    memcpy((void*)newcontent,(void*)bb->content,sizeof(char)*bb->length);
59  }
60  if(bb->content != NULLefree(bb->content);
61  bb->content=newcontent;
62  bb->alloc=sz;
63  return TRUE;
64}
65
66void
67bbFree(Bytebufferbb)
68{
69  if(bb == NULL) return;
70  if(bb->content != NULLefree(bb->content);
71  efree(bb);
72}
73
74int
75bbSetlength(Bytebufferbb, const unsigned int sz)
76{
77  if(bb == NULL) return bbFail();
78  if(bb->length < sz) {
79      if(!bbSetalloc(bb,sz)) return bbFail();
80  }
81  bb->length = sz;
82  return TRUE;
83}
84
85int
86bbFill(Bytebufferbb, const char fill)
87{
88  unsigned int i;
89  if(bb == NULL) return bbFail();
90  for(i=0;i<bb->length;i++) bb->content[i] = fill;
91  return TRUE;
92}
93
94int
95bbGet(Bytebufferbb, unsigned int index)
96{
97  if(bb == NULL) return -1;
98  if(index >= bb->length) return -1;
99  return bb->content[index];
100}
101
102int
103bbSet(Bytebufferbb, unsigned int index, char elem)
104{
105  if(bb == NULL) return bbFail();
106  if(index >= bb->length) return bbFail();
107  bb->content[index] = elem;
108  return TRUE;
109}
110
111int
112bbAppend(Bytebufferbb, char elem)
113{
114  if(bb == NULL) return bbFail();
115  /* We need space for the char + null */
116  while(bb->length+1 >= bb->alloc) {
117    if(!bbSetalloc(bb,0))
118      return bbFail();
119  }
120  bb->content[bb->length] = elem;
121  bb->length++;
122  bb->content[bb->length] = '\0';
123  return TRUE;
124}
125
126/* This assumes s is a null terminated string*/
127int
128bbCat(Bytebufferbb, const char* s)
129{
130    bbAppendn(bb,(void*)s,strlen(s)+1); /* include trailing null*/
131    /* back up over the trailing null*/
132    if(bb->length == 0) return bbFail();
133    bb->length--;
134    return 1;
135}
136
137int
138bbCatbuf(Bytebufferbb, const Bytebuffers)
139{
140    if(bbLength(s) > 0)
141 bbAppendn(bb,bbContents(s),bbLength(s));
142    bbNull(bb);
143    return 1;
144}
145
146int
147bbAppendn(Bytebufferbb, const void* elem, const unsigned int n0)
148{
149  unsigned int n = n0;
150  if(bb == NULL || elem == NULL) return bbFail();
151  if(n == 0) {n = strlen((char*)elem);}
152  while(!bbNeed(bb,(n+1))) {if(!bbSetalloc(bb,0)) return bbFail();}
153  memcpy((void*)&bb->content[bb->length],(void*)elem,n);
154  bb->length += n;
155  bb->content[bb->length] = '\0';
156  return TRUE;
157}
158
159int
160bbInsert(Bytebufferbb, const unsigned int index, const char elem)
161{
162  char tmp[2];
163  tmp[0]=elem;
164  return bbInsertn(bb,index,tmp,1);
165}
166
167int
168bbInsertn(Bytebufferbb, const unsigned int index, const char* elem, const unsigned int n)
169{
170  unsigned int i;
171  int j;
172  unsigned int newlen = 0;
173
174  if(bb == NULL) return bbFail();
175
176  newlen = bb->length + n;
177
178  if(newlen >= bb->alloc) {
179    if(!bbExtend(bb,n)) return bbFail();
180  }
181  /*
182index=0
183n=3
184len=3
185newlen=6
186a b c
187x y z a b c
188-----------
1890 1 2 3 4 5
190
191i=0 1 2
192j=5 4 3
193  2 1 0
194*/
195  for(j=newlen-1,i=index;i<bb->length;i++) {
196    bb->content[j]=bb->content[j-n];
197  }
198  memcpy((void*)(bb->content+index),(void*)elem,n);
199  bb->length += n;
200  return TRUE;
201}
202
203/*! Pop head off of a byte buffer.
204 *
205 * @param Bytebuffer bb Pointer to Bytebuffer.
206 * @param char* pelem pointer to location for head element.
207 *
208 * @return Returns TRUE on success.
209 */
210int bbHeadpop(Bytebufferbb, char* pelem)
211{
212  if(bb == NULL) return bbFail();
213  if(bb->length == 0) return bbFail();
214  *pelem = bb->content[0];
215  memmove((void*)&bb->content[0],
216          (void*)&bb->content[1],
217          sizeof(char)*(bb->length - 1));
218  bb->length--;
219  return TRUE;
220}
221
222int
223bbTailpop(Bytebufferbb, char* pelem)
224{
225  if(bb == NULL) return bbFail();
226  if(bb->length == 0) return bbFail();
227  *pelem = bb->content[bb->length-1];
228  bb->length--;
229  return TRUE;
230}
231
232int
233bbHeadpeek(Bytebufferbb, char* pelem)
234{
235  if(bb == NULL) return bbFail();
236  if(bb->length == 0) return bbFail();
237  *pelem = bb->content[0];
238  return TRUE;
239}
240
241int
242bbTailpeek(Bytebufferbb, char* pelem)
243{
244  if(bb == NULL) return bbFail();
245  if(bb->length == 0) return bbFail();
246  *pelem = bb->content[bb->length - 1];
247  return TRUE;
248}
249
250char*
251bbDup(const Bytebufferbb)
252{
253    char* result = (char*)emalloc(bb->length+1);
254    memcpy((void*)result,(const void*)bb->content,bb->length);
255    result[bb->length] = '\0'; /* just in case it is a string*/
256    return result;
257}
258
259int
260bbSetcontents(Bytebufferbb, char* contents, const unsigned int alloc)
261{
262    if(bb == NULL) return bbFail();
263    bbClear(bb);
264    if(!bb->nonextendible && bb->content != NULLefree(bb->content);
265    bb->content = contents;
266    bb->length = 0;
267    bb->alloc = alloc;
268    bb->nonextendible = 1;
269    return 1;
270}
271
272/* Add invisible NULL terminator */
273int
274bbNull(Bytebufferbb)
275{
276    bbAppend(bb,'\0');
277    bb->length--;
278    return 1;
279}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed