1 /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2    See the COPYRIGHT file for more information. */
3 
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 
8 #include "ncbytes.h"
9 
10 #ifndef TRUE
11 #define TRUE 1
12 #endif
13 #ifndef FALSE
14 #define FALSE 0
15 #endif
16 
17 #define DEFAULTALLOC 1024
18 #define ALLOCINCR 1024
19 
20 static int ncbytesdebug = 1;
21 
22 static long
ncbytesfail(void)23 ncbytesfail(void)
24 {
25     fflush(stdout);
26     fprintf(stderr,"bytebuffer failure\n");
27     fflush(stderr);
28     if(ncbytesdebug) abort();
29     return FALSE;
30 }
31 
32 NCbytes*
ncbytesnew(void)33 ncbytesnew(void)
34 {
35   NCbytes* bb = (NCbytes*)malloc(sizeof(NCbytes));
36   if(bb == NULL) return (NCbytes*)ncbytesfail();
37   bb->alloc=0;
38   bb->length=0;
39   bb->content=NULL;
40   bb->nonextendible = 0;
41   return bb;
42 }
43 
44 int
ncbytessetalloc(NCbytes * bb,unsigned int sz)45 ncbytessetalloc(NCbytes* bb, unsigned int sz)
46 {
47   char* newcontent;
48   if(bb == NULL) return ncbytesfail();
49   if(sz <= 0) {sz = (bb->alloc?2*bb->alloc:DEFAULTALLOC);}
50   if(bb->alloc >= sz) return TRUE;
51   if(bb->nonextendible) return ncbytesfail();
52   newcontent=(char*)calloc(sz,sizeof(char));
53   if(bb->alloc > 0 && bb->length > 0 && bb->content != NULL) {
54     memcpy((void*)newcontent,(void*)bb->content,sizeof(char)*bb->length);
55   }
56   if(bb->content != NULL) free(bb->content);
57   bb->content=newcontent;
58   bb->alloc=sz;
59   return TRUE;
60 }
61 
62 void
ncbytesfree(NCbytes * bb)63 ncbytesfree(NCbytes* bb)
64 {
65   if(bb == NULL) return;
66   if(!bb->nonextendible && bb->content != NULL) free(bb->content);
67   free(bb);
68 }
69 
70 int
ncbytessetlength(NCbytes * bb,unsigned int sz)71 ncbytessetlength(NCbytes* bb, unsigned int sz)
72 {
73   if(bb == NULL) return ncbytesfail();
74   if(sz > bb->alloc) {if(!ncbytessetalloc(bb,sz)) return ncbytesfail();}
75   bb->length = sz;
76   return TRUE;
77 }
78 
79 int
ncbytesfill(NCbytes * bb,char fill)80 ncbytesfill(NCbytes* bb, char fill)
81 {
82   unsigned int i;
83   if(bb == NULL) return ncbytesfail();
84   for(i=0;i<bb->length;i++) bb->content[i] = fill;
85   return TRUE;
86 }
87 
88 int
ncbytesget(NCbytes * bb,unsigned int index)89 ncbytesget(NCbytes* bb, unsigned int index)
90 {
91   if(bb == NULL) return -1;
92   if(index >= bb->length) return -1;
93   return bb->content[index];
94 }
95 
96 int
ncbytesset(NCbytes * bb,unsigned int index,char elem)97 ncbytesset(NCbytes* bb, unsigned int index, char elem)
98 {
99   if(bb == NULL) return ncbytesfail();
100   if(index >= bb->length) return ncbytesfail();
101   bb->content[index] = elem;
102   return TRUE;
103 }
104 
105 int
ncbytesappend(NCbytes * bb,char elem)106 ncbytesappend(NCbytes* bb, char elem)
107 {
108   if(bb == NULL) return ncbytesfail();
109   if(bb->length >= bb->alloc) if(!ncbytessetalloc(bb,0)) return ncbytesfail();
110   bb->content[bb->length] = elem;
111   bb->length++;
112   return TRUE;
113 }
114 
115 /* This assumes s is a null terminated string*/
116 int
ncbytescat(NCbytes * bb,char * s)117 ncbytescat(NCbytes* bb, char* s)
118 {
119     ncbytesappendn(bb,(void*)s,strlen(s)+1); /* include trailing null*/
120     /* back up over the trailing null*/
121     if(bb->length == 0) return ncbytesfail();
122     bb->length--;
123     return 1;
124 }
125 
126 int
ncbytesappendn(NCbytes * bb,void * elem,unsigned int n)127 ncbytesappendn(NCbytes* bb, void* elem, unsigned int n)
128 {
129   if(bb == NULL || elem == NULL) return ncbytesfail();
130   if(n == 0) {n = strlen((char*)elem);}
131   while(!ncbytesavail(bb,n)) {if(!ncbytessetalloc(bb,0)) return ncbytesfail();}
132   memcpy((void*)&bb->content[bb->length],(void*)elem,n);
133   bb->length += n;
134   return TRUE;
135 }
136 
137 int
ncbytesprepend(NCbytes * bb,char elem)138 ncbytesprepend(NCbytes* bb, char elem)
139 {
140   int i; /* do not make unsigned */
141   if(bb == NULL) return ncbytesfail();
142   if(bb->length >= bb->alloc) if(!ncbytessetalloc(bb,0)) return ncbytesfail();
143   /* could we trust memcpy? instead */
144   for(i=bb->alloc;i>=1;i--) {bb->content[i]=bb->content[i-1];}
145   bb->content[0] = elem;
146   bb->length++;
147   return TRUE;
148 }
149 
150 char*
ncbytesdup(NCbytes * bb)151 ncbytesdup(NCbytes* bb)
152 {
153     char* result = (char*)malloc(bb->length+1);
154     memcpy((void*)result,(const void*)bb->content,bb->length);
155     result[bb->length] = '\0'; /* just in case it is a string*/
156     return result;
157 }
158 
159 char*
ncbytesextract(NCbytes * bb)160 ncbytesextract(NCbytes* bb)
161 {
162     char* result = bb->content;
163     bb->alloc = 0;
164     bb->length = 0;
165     bb->content = NULL;
166     return result;
167 }
168 
169 int
ncbytessetcontents(NCbytes * bb,char * contents,unsigned int alloc)170 ncbytessetcontents(NCbytes* bb, char* contents, unsigned int alloc)
171 {
172     if(bb == NULL) return ncbytesfail();
173     ncbytesclear(bb);
174     if(!bb->nonextendible && bb->content != NULL) free(bb->content);
175     bb->content = contents;
176     bb->length = 0;
177     bb->alloc = alloc;
178     bb->nonextendible = 1;
179     return 1;
180 }
181 
182 /* Null terminate the byte string without extending its length */
183 /* For debugging */
184 int
ncbytesnull(NCbytes * bb)185 ncbytesnull(NCbytes* bb)
186 {
187     ncbytesappend(bb,'\0');
188     bb->length--;
189     return 1;
190 }
191 
192