1 /*-----------------------------------------------------------------------
2
3 File : clb_dstrings.c
4
5 Author: Stephan Schulz
6
7 Implementation of the Dynamic String functions.
8
9 Copyright 1998, 1999 by the author.
10 This code is released under the GNU General Public Licence and
11 the GNU Lesser General Public License.
12 See the file COPYING in the main E directory for details..
13 Run "eprover -h" for contact information.
14
15 Created: Fri Aug 15 17:17:20 MET DST 1997 - New
16
17 -----------------------------------------------------------------------*/
18
19 #include "clb_dstrings.h"
20
21
22
23 /*---------------------------------------------------------------------*/
24 /* Global Variables */
25 /*---------------------------------------------------------------------*/
26
27 char NullStr[] = "";
28
29 /*---------------------------------------------------------------------*/
30 /* Forward Declarations */
31 /*---------------------------------------------------------------------*/
32
33
34 /*---------------------------------------------------------------------*/
35 /* Internal Functions */
36 /*---------------------------------------------------------------------*/
37
38
39
40 /*---------------------------------------------------------------------*/
41 /* Exported Functions */
42 /*---------------------------------------------------------------------*/
43
44
45 /*-----------------------------------------------------------------------
46 //
47 // Function: DStrAlloc()
48 //
49 // Return a pointer to an initialized DStrCell.
50 //
51 // Global Variables: -
52 //
53 // Side Effects : Memory operations
54 //
55 /----------------------------------------------------------------------*/
56
DStrAlloc(void)57 DStr_p DStrAlloc(void)
58 {
59 DStr_p handle = DStrCellAlloc();
60
61 handle->string = NULL;
62 handle->mem = 0;
63 handle->len = 0;
64 handle->refs = 1;
65
66 return handle;
67 }
68
69 /*-----------------------------------------------------------------------
70 //
71 // Function: DStrFree()
72 //
73 // Decrease the reference counter. If it is equal to 0, free both
74 // the DStr-Cell and the contained string.
75 //
76 // Global Variables: -
77 //
78 // Side Effects : Memory Operations
79 //
80 /----------------------------------------------------------------------*/
81
DStrFree(DStr_p junk)82 void DStrFree(DStr_p junk)
83 {
84 assert(junk);
85 assert(junk->refs >= 1);
86
87 junk->refs--;
88
89 if(!junk->refs)
90 {
91 if(junk->string)
92 {
93 FREE(junk->string);
94 }
95 DStrCellFree(junk);
96 }
97 }
98
99 /*-----------------------------------------------------------------------
100 //
101 // Function: DStrAppendStr()
102 //
103 // Append a C-String to a DStr efficiently
104 //
105 // Global Variables: -
106 //
107 // Side Effects : Memory operations
108 //
109 /----------------------------------------------------------------------*/
110
DStrAppendStr(DStr_p strdes,char * newpart)111 char* DStrAppendStr(DStr_p strdes, char* newpart)
112 {
113 long newlen,
114 newmem;
115
116 assert(strdes);
117 assert(newpart);
118
119 newlen = strlen(newpart);
120 newmem = strdes->mem;
121
122 while(strdes->len+newlen >= newmem) /* I expect this loop to be
123 computed at most once in
124 the average case, so it
125 should be more efficient
126 than the direct computation
127 (which requires a
128 division. */
129 {
130 newmem += DSTRGROW;
131 }
132 if(newmem > strdes->mem)
133 {
134 strdes->string = SecureRealloc(strdes->string, newmem);
135 strdes->mem = newmem;
136 strdes->string[strdes->len] = '\0';
137 }
138 strcat(strdes->string+strdes->len, newpart);
139 strdes->len += newlen;
140
141 return strdes->string;
142 }
143
144 /*-----------------------------------------------------------------------
145 //
146 // Function: DStrAppendChar()
147 //
148 // Append a single character to a DStr. This is the operation that
149 // will probably be called with the highest frequency, so I try to
150 // make it efficient.
151 //
152 // Global Variables: -
153 //
154 // Side Effects : Memory operations
155 //
156 /----------------------------------------------------------------------*/
157
DStrAppendChar(DStr_p strdes,char newch)158 char* DStrAppendChar(DStr_p strdes, char newch)
159 {
160 assert(strdes);
161
162 if(strdes->len+1 >= strdes->mem)
163 {
164 strdes->string = SecureRealloc(strdes->string, strdes->len+DSTRGROW);
165 strdes->mem = strdes->len+DSTRGROW;
166 }
167 strdes->string[strdes->len] = newch;
168 strdes->len++;
169 strdes->string[strdes->len] = '\0';
170
171 return strdes->string;
172 }
173
174 /*-----------------------------------------------------------------------
175 //
176 // Function: DStrAppendBuffer()
177 //
178 // Append a (not necessarily 0-terminated) buffer to the end of a
179 // DStr.
180 //
181 // Global Variables: -
182 //
183 // Side Effects : Memory operations
184 //
185 /----------------------------------------------------------------------*/
186
DStrAppendBuffer(DStr_p strdes,char * buf,int len)187 char* DStrAppendBuffer(DStr_p strdes, char* buf, int len)
188 {
189 int i;
190
191 assert(strdes);
192 assert(buf);
193
194 for(i=0; i<len; i++)
195 {
196 DStrAppendChar(strdes, buf[i]);
197 }
198 return strdes->string;
199 }
200
201
202
203 /*-----------------------------------------------------------------------
204 //
205 // Function: DStrAppendInt()
206 //
207 // Append the string representation of a long number to a DStr.
208 //
209 // Global Variables: ErrStr
210 //
211 // Side Effects : By DStrAppendStr(), changes ErrStr
212 //
213 /----------------------------------------------------------------------*/
214
DStrAppendInt(DStr_p strdes,long newpart)215 char* DStrAppendInt(DStr_p strdes, long newpart)
216 {
217 sprintf(ErrStr, "%ld", newpart);
218 return DStrAppendStr(strdes, ErrStr);
219 }
220
221
222
223 /*-----------------------------------------------------------------------
224 //
225 // Function: DStrAppendStrArray()
226 //
227 // Append the elements of the NULL terminated array to str as a
228 // separator separated list.
229 //
230 // Global Variables: -
231 //
232 // Side Effects : -
233 //
234 /----------------------------------------------------------------------*/
235
DStrAppendStrArray(DStr_p strdes,char * array[],char * separator)236 char* DStrAppendStrArray(DStr_p strdes, char* array[], char*
237 separator)
238 {
239 int i=0;
240
241 if(array[0])
242 {
243 DStrAppendStr(strdes, array[0]);
244 for(i=1; array[i]; i++)
245 {
246 DStrAppendStr(strdes, separator);
247 DStrAppendStr(strdes, array[i]);
248 }
249 }
250 return strdes->string;
251 }
252
253
254 /*-----------------------------------------------------------------------
255 //
256 // Function: DStrDeleteLastChar()
257 //
258 // If String is not empty, delete last character and return
259 // is. Otherwise return '\0'.
260 //
261 // Global Variables: -
262 //
263 // Side Effects : -
264 //
265 /----------------------------------------------------------------------*/
266
DStrDeleteLastChar(DStr_p strdes)267 char DStrDeleteLastChar(DStr_p strdes)
268 {
269 char res = '\0';
270
271 assert(strdes);
272 if(strdes->len > 0)
273 {
274 strdes->len--;
275 res = strdes->string[strdes->len];
276 assert(res);
277 strdes->string[strdes->len] = '\0';
278 }
279 return res;
280 }
281
282
283 /*-----------------------------------------------------------------------
284 //
285 // Function: DStrView()
286 //
287 // Return a pointer to the stored C-string. This is guaranteed to stay
288 // fresh as long as no other DStr-Operation is performed on the
289 // string. The user is responsible for the use of this pointer - in
290 // particular, write-operations on the string should not change the
291 // lenght of the string, or it will become corrupted!
292 //
293 // Global Variables: -
294 //
295 // Side Effects : -
296 //
297 /----------------------------------------------------------------------*/
298
DStrView(DStr_p strdes)299 char* DStrView(DStr_p strdes)
300 {
301 assert(strdes);
302
303 if(strdes->string)
304 {
305 return strdes->string;
306 }
307 return NullStr;
308 }
309
310
311 /*-----------------------------------------------------------------------
312 //
313 // Function: DStrAddress()
314 //
315 // Return the address of the given character in the DStr, or 0 if
316 // the string has less than index+1 chars.
317 //
318 // Global Variables: -
319 //
320 // Side Effects : -
321 //
322 /----------------------------------------------------------------------*/
323
DStrAddress(DStr_p strdes,int index)324 char* DStrAddress(DStr_p strdes, int index)
325 {
326 if(index>strdes->len)
327 {
328 return NULL;
329 }
330 return strdes->string+index;
331 }
332
333
334
335 /*-----------------------------------------------------------------------
336 //
337 // Function: DStrCopy()
338 //
339 // Return a pointer to a copy of the stored string. The user is
340 // responsible for freeing the memory (via free()/FREE()).
341 //
342 // Global Variables: -
343 //
344 // Side Effects : Memort operations
345 //
346 /----------------------------------------------------------------------*/
347
DStrCopy(DStr_p strdes)348 char* DStrCopy(DStr_p strdes)
349 {
350 char* handle;
351
352 assert(strdes);
353
354 if(strdes->string)
355 {
356 /* As we know the length, this should be more efficient than
357 using SecureStrdup() */
358
359 handle = SecureMalloc(strdes->len+1);
360 strcpy(handle,strdes->string);
361 return handle;
362 }
363 return SecureStrdup(NullStr);
364 }
365
366
367 /*-----------------------------------------------------------------------
368 //
369 // Function: DStrCopyCore()
370 //
371 // Return a pointer to a copy of the stored string without the first
372 // and last character (this is useful for stripping quotes off
373 // string literals). The user is responsible for freeing the memory
374 // (via free()/FREE()). Fails if string has less than two characters.
375 //
376 // Global Variables: -
377 //
378 // Side Effects : Memory operations
379 //
380 /----------------------------------------------------------------------*/
381
DStrCopyCore(DStr_p strdes)382 char* DStrCopyCore(DStr_p strdes)
383 {
384 char* handle;
385
386 assert(strdes);
387 assert(strdes->string);
388 assert(strdes->len >= 2);
389
390 handle = SecureMalloc(strdes->len-1);
391 strncpy(handle,strdes->string+1, strdes->len-2);
392 handle[strdes->len-2] = 0;
393 return handle;
394 }
395
396
397
398 /*-----------------------------------------------------------------------
399 //
400 // Function: DStrSet()
401 //
402 // Set a dstring to a given C-String.
403 //
404 // Global Variables: -
405 //
406 // Side Effects : Via DStrAppendStr()
407 //
408 /----------------------------------------------------------------------*/
409
DStrSet(DStr_p strdes,char * string)410 char* DStrSet(DStr_p strdes, char* string)
411 {
412 assert(strdes);
413 assert(string);
414
415 DStrReset(strdes);
416 DStrAppendStr(strdes,string);
417
418 return strdes->string;
419 }
420
421
422 /*-----------------------------------------------------------------------
423 //
424 // Function: DStrLen()
425 //
426 // Return the length of a stored string (efficiency hack...)
427 //
428 // Global Variables: -
429 //
430 // Side Effects : -
431 //
432 /----------------------------------------------------------------------*/
433
DStrLen(DStr_p strdes)434 long DStrLen(DStr_p strdes)
435 {
436 assert(strdes);
437
438 return strdes->len;
439 }
440
441
442 /*-----------------------------------------------------------------------
443 //
444 // Function: DStrReset()
445 //
446 // Set the string to "" efficiently (does _not_ change internal
447 // memory - call this to e.g. reinitialize a string in a loop)
448 //
449 // Global Variables: -
450 //
451 // Side Effects : -
452 //
453 /----------------------------------------------------------------------*/
454
DStrReset(DStr_p strdes)455 void DStrReset(DStr_p strdes)
456 {
457 assert(strdes);
458
459 if(strdes->string)
460 {
461 strdes->string[0] = '\0';
462 strdes->len = 0;
463 }
464 }
465
466
467 /*-----------------------------------------------------------------------
468 //
469 // Function: DStrMinimize()
470 //
471 // Minimize the space used to store the string in strdes.
472 //
473 // Global Variables: -
474 //
475 // Side Effects : -
476 //
477 /----------------------------------------------------------------------*/
478
DStrMinimize(DStr_p strdes)479 void DStrMinimize(DStr_p strdes)
480 {
481 assert(strdes);
482
483 if(strdes->string)
484 {
485 if(strdes->len)
486 {
487 strdes->string = SecureRealloc(strdes->string,
488 strdes->len+1);
489 strdes->mem = strdes->len+1;
490 }
491 else
492 {
493 FREE(strdes->string);
494 strdes->string = NULL; /* Be safe... */
495 strdes->mem = 0;
496 }
497 }
498 }
499
500
501 /*---------------------------------------------------------------------*/
502 /* End of File */
503 /*---------------------------------------------------------------------*/
504