Imported Upstream version 0.4.8
[platform/upstream/libsmi.git] / tools / dstring.c
1 /*
2  * dstring.c --
3  *
4  *      Implementation of the dynamic string abstract data type.
5  *
6  * Copyright (c) 2006 Juergen Schoenwaelder, International University Bremen.
7  *
8  * See the file "COPYING" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * @(#) $Id: smilint.c 1867 2004-10-06 13:45:31Z strauss $
12  */
13
14 #include <config.h>
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdarg.h>
19 #include <stdio.h>
20 #ifdef HAVE_WIN_H
21 #include "win.h"
22 #endif
23
24 #include "dstring.h"
25
26 #if !defined va_copy
27 # if defined __va_copy
28 #  define va_copy __va_copy                     /* C99 draft proposal */
29 # else
30 #  define va_copy(lhs,rhs) (lhs) = (rhs)
31 # endif
32 #endif
33
34 #if 0
35 /* These functions should not be needed if inlining works properly. */
36 char*
37 dstring_str(dstring_t *ds)
38 {
39     return ds ? ds->str : NULL;
40 }
41
42 size_t
43 dstring_len(dstring_t *ds)
44 {
45     return ds ? ds->len : 0;
46 }
47 #endif
48
49 static inline dstring_t*
50 dstring_grow(dstring_t *ds, size_t len)
51 {
52     if (ds) {
53         ds->str = realloc(ds->str, len + 1);
54         if (! ds->str) {
55             exit(EXIT_FAILURE);
56         }
57         ds->str[len] = '\0';
58         ds->len = len;
59     }
60     return ds;
61 }
62
63 dstring_t*
64 dstring_new(void)
65 {
66     dstring_t *ds;
67
68     ds = calloc(1, sizeof(dstring_t));
69     if (! ds) {
70         exit(EXIT_FAILURE);
71     }
72     return dstring_grow(ds, 0);
73 }
74
75 dstring_t*
76 dstring_delete(dstring_t *ds)
77 {
78     if (ds) {
79         if (ds->str) free(ds->str);
80         free(ds);
81     }
82     return NULL;
83 }
84
85 dstring_t*
86 dstring_assign(dstring_t *ds, const char *s)
87 {
88     if (ds && s) {
89         ds = dstring_grow(ds, strlen(s));
90         strcpy(ds->str, s);
91     }
92     return ds;
93 }
94
95 dstring_t*
96 dstring_append(dstring_t *ds, const char *s)
97 {
98     if (ds && s) {
99         ds = dstring_grow(ds, ds->len + strlen(s));
100         strcat(ds->str, s);
101     }
102     return ds;
103 }
104
105
106 dstring_t*
107 dstring_append_char(dstring_t *ds, const char c)
108 {
109     if (ds) {
110         ds = dstring_grow(ds, ds->len + 1);
111         ds->str[ds->len-1] = c;
112     }
113     return ds;
114 }
115
116
117 dstring_t*
118 dstring_concat(dstring_t *ds, ...)
119 {
120     va_list ap;
121     const char *s;
122
123     if (ds) {
124         va_start(ap, ds);
125         for (s = va_arg(ap, char*); s; s = va_arg(ap, char*)) {
126             ds = dstring_append(ds, s);
127         }
128         va_end(ap);
129     }
130     return ds;
131 }
132
133 dstring_t*
134 dstring_append_printf(dstring_t *ds, const char *format, ...)
135 {
136     va_list ap;
137
138     va_start(ap, format);
139     ds = dstring_append_vprintf(ds, format, ap);
140     va_end(ap);
141     return ds;
142 }
143
144 dstring_t *
145 dstring_append_vprintf(dstring_t *ds, const char *format, va_list _ap)
146 {
147     int n, o;
148     va_list ap;
149     
150     if (ds) {
151         o = ds->len;
152         while (1) {
153             va_copy(ap, _ap);
154             n = vsnprintf(ds->str + o, ds->len+1 - o, format, ap);
155             va_end(ap);
156             if (n > -1 && n+o <= ds->len) {
157                 if (n+o < ds->len) {
158                     dstring_truncate(ds, n+o);
159                 }
160                 return ds;
161             }
162             if (n > 0) {
163                 ds = dstring_grow(ds, n + o);                   /* C99 */
164             } else {
165                 ds = dstring_grow(ds, ds->len + ds->len);       /* GLIBC */
166             }
167         }
168     }
169
170     return ds;
171 }
172
173 dstring_t*
174 dstring_printf(dstring_t *ds, const char *format, ...)
175 {
176     va_list ap;
177
178     va_start(ap, format);
179     ds = dstring_vprintf(ds, format, ap);
180     va_end(ap);
181     return ds;
182 }
183
184 dstring_t*
185 dstring_vprintf(dstring_t *ds, const char *format, va_list _ap)
186 {
187     int n;
188     va_list ap;
189
190     if (ds) {
191         while (1) {
192             va_copy(ap, _ap);
193             n = vsnprintf(ds->str, ds->len+1, format, ap);
194             va_end(ap);
195             if (n > -1 && n <= ds->len) {
196                 if (n < ds->len) {
197                     dstring_truncate(ds, n);
198                 }
199                 return ds;
200             }
201             if (n > 0) {
202                 ds = dstring_grow(ds, n);                       /* C99 */
203             } else {
204                 ds = dstring_grow(ds, ds->len + ds->len);       /* GLIBC */
205             }
206         }
207     }
208     return ds;
209 }
210
211 dstring_t*
212 dstring_truncate(dstring_t *ds, int len)
213 {
214     if (ds && len < ds->len) {
215         ds = dstring_grow(ds, len);
216     }
217     return ds;
218 }
219
220 dstring_t*
221 dstring_expand(dstring_t *ds, int len, char fill)
222 {
223     if (ds && len > ds->len) {
224         int i, old = ds->len;
225         ds = dstring_grow(ds, len);
226         for (i = old; i < len; i++) {
227             ds->str[i] = fill;
228         }
229     }
230     return ds;
231 }