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