1 /* Copyright 1999 Enhanced Software Technologies Inc.
2 * Released for public use under a BSD-style license.
3 * See file "LICENSE" for more information.
4 *
5 * dstring.c -- dynamically allocated string functions.
6 *
7 * RCS CHANGE LOG
8 * $Log: dstring.c,v $
9 * Revision 1.1.1.1 2001/05/17 17:11:01 elgreen
10 * Initial checkin
11 *
12 * Revision 1.3 2000/12/12 16:41:21 eric
13 * aescrypt 0.6 (large patch by Peter Pentchev).
14 *
15 * Revision 1.2 2000/04/05 22:09:19 eric
16 * Daily checkin...
17 *
18 * Revision 1.1 2000/03/28 23:54:28 eric
19 * Initial checkin -- aescrypt/aesget
20 *
21 * Revision 1.8 1999/11/18 16:23:36 eric
22 * More mods to make it work. Start of the 'rsh' functionality.
23 *
24 * Revision 1.7 1999/11/09 18:57:29 eric
25 * Re-wrote 'trim' routines :-(.
26 *
27 * Revision 1.6 1999/11/03 23:26:43 eric
28 * Fixed some problems with headers and dstring.c :-(.
29 *
30 * Revision 1.5 1999/09/30 20:32:28 eric
31 * Refreshed after Richard foobared the CVS archive
32 *
33 * Revision 1.4 1999/09/28 19:33:53 eric
34 * Add d_lpad and d_rpad routines.
35 *
36 * Revision 1.3 1999/09/13 16:08:23 eric
37 * Added Ocotillo licensing info.
38 *
39 * Revision 1.2 1999/08/27 23:22:59 eric
40 * Misc. changes...
41 *
42 * Revision 1.1 1999/08/25 22:08:48 eric
43 * Initial revision, dynamic string routines for "C".
44 *
45 * $Date: 2001/05/17 17:11:01 $
46 */
47
48 #include <stdio.h>
49 #include <string.h>
50 #include <ctype.h>
51 #include <stdlib.h>
52
53 #include "dstring.h"
54
55 static char *d_ltrim(char *src);
56 static char *d_rtrim(char *src);
57
58 /* Returns a line of EXACTLY the length of input. Does have a limit, so we
59 * don't exhaust all virtual memory. Does use more CPU time alloc'ing and
60 * un-alloc'ing our temporary buffer, but so it goes :-(.
61 */
d_getline(FILE * file,int limit)62 char *d_getline(FILE *file, int limit) {
63 char *result; /* result of fgets */
64 char *retvalue; /* return value, our new string. */
65 char *buffer = (char *)malloc(limit+1);
66 int newlen;
67
68 if (!buffer) {
69 return NULL; /* sorry, could not malloc! */
70 }
71 result = fgets(buffer,limit,file);
72 if (!result) { /* We have an error! Return it to our caller */
73 free(buffer);
74 return NULL; /* Sorry! */
75 }
76 newlen=strlen(buffer);
77 retvalue=(char *)malloc(newlen+1);
78 if (!retvalue) {
79 free(buffer);
80 return NULL; /* sorry, could not malloc ! */
81 }
82 snprintf(retvalue, newlen + 1, "%s", buffer);
83 free(buffer);
84 return retvalue;
85 }
86
87
88 /********************************************************************
89 **** NOTICE ON D_LPAD AND D_RPAD!***
90 * These share a great deal of common code. In fact, there is
91 * exactly one line different between the two. This SHOULD be re-written
92 * to actually call a "d_pad" routine that has "left" and "right" flag
93 * e.g. 0=pad left, 1=pad right. If anybody feels like doing it, go
94 * for it (and do an inline function or macro to convert d_lpad to
95 * d_pad(src,ch,len,direction).
96 *********************************************************************/
97
98 /* add whitespace or other chars to left of a string to pad it out to a
99 * given length.
100 */
101
d_lpad(char * src,int ch,int len)102 char *d_lpad(char *src, int ch, int len) {
103 char *result;
104 char *lpad; /* leftmost chars to be inserted */
105 int curlen;
106 int numneeded;
107 int i;
108
109 curlen=strlen(src);
110 if (curlen >= len) {
111 return d_dup(src); /* just duplicate it and return. */
112 }
113
114 /* if we get here, it's shorter, and we need to pad some stuff.
115 * if it's 5 chars and we need 10, we would need a string of
116 * 10-5 (5) chars, plus allocate an extra for the trailing space.
117 */
118 numneeded=len-curlen;
119 lpad=(char *) malloc(numneeded+1);
120 if (!lpad) {
121 return NULL; /* Out-of-memory error! */
122 }
123
124 for (i=0;i<numneeded;i++) {
125 lpad[i]=(char)ch;
126 }
127 lpad[numneeded]=0;
128 result=d_cat(lpad,src);
129 free(lpad); /* eliminate a potential memory leak! */
130 return result; /* and done! */
131 }
132
133 /* add whitespace or other chars to right of a string to pad it out to a
134 * given length.
135 */
136
d_rpad(char * src,int ch,int len)137 char *d_rpad(char *src, int ch, int len) {
138 char *result;
139 char *rpad; /* leftmost chars to be inserted */
140 int curlen;
141 int numneeded;
142 int i;
143
144 curlen=strlen(src);
145 if (curlen >= len) {
146 return d_dup(src); /* just duplicate it and return. */
147 }
148
149 /* if we get here, it's shorter, and we need to pad some stuff.
150 * if it's 5 chars and we need 10, we would need a string of
151 * 10-5 (5) chars, plus allocate an extra for the trailing space.
152 */
153 numneeded=len-curlen;
154 rpad=(char *)malloc(numneeded+1);
155 if (!rpad) {
156 return NULL; /* Out-of-memory error! */
157 }
158
159 for (i=0;i<numneeded;i++) {
160 rpad[i]=(char)ch;
161 }
162 rpad[numneeded]=0;
163 result=d_cat(src,rpad);
164 free(rpad); /* eliminate a potential memory leak! */
165 return result; /* and done! */
166 }
167
168 /* Trim all the whitespace off the LEFT of a string, returning trimmed
169 * str.
170 */
171
d_ltrim(char * src)172 static char *d_ltrim(char *src) {
173 char *dest;
174 char *walkptr;
175 size_t len;
176
177 walkptr=src;
178 while (*walkptr && isspace(*walkptr)) {
179 walkptr++;
180 }
181
182 len = strlen(walkptr);
183 dest=(char *)malloc(len + 1);
184 if (!dest) {
185 return NULL; /* sorry, out of memory! */
186 }
187 snprintf(dest, len + 1, "%s", walkptr);
188 return dest; /* and return! */
189 }
190
191 /* Trim all the white space off the RIGHT of a string, returning trimmed
192 * str. Actually returns a pointer to same amount of malloc'ed space,
193 * I don't think that's going to be a problem...
194 */
d_rtrim(char * src)195 static char *d_rtrim(char *src) {
196 int i,j,len;
197 char *dest;
198
199 len=strlen(src);
200 dest=(char *)malloc(len+1);
201 if (!dest) return NULL; /* sorry, out of memory! */
202 snprintf(dest, len + 1, "%s", src);
203
204 if (!*dest) {
205 return dest; /* empty string! */
206 }
207
208
209
210 i=0;
211 j=len;
212 while ( (i < j) && isspace(dest[j-1])) {
213 j--;
214 }
215 dest[j]=0;
216 return dest;
217
218 }
219
220 /* trim whitespace from left and right of a string, returning trimmed str
221 * we call ltrim last because it returns a block of memory that's the
222 * actual length of our newly-trimmed string (rtrim doesn't, due to
223 * efficiency reasons).
224 */
225
d_trim(char * src)226 char *d_trim(char *src) {
227 char *ltrim;
228 char *rtrim;
229
230 if (!*src) {
231 return src;
232 } else {
233 rtrim=d_rtrim(src);
234 if (!*rtrim) { /* if it stripped whole thingy, just return */
235 return rtrim;
236 }
237 ltrim=d_ltrim(rtrim);
238 free(rtrim);
239 return ltrim;
240 }
241 }
242
243 /* Duplicate a string, malloc'ing the buffer with it. */
d_dup(char * str)244 char *d_dup(char *str) {
245 char *buffer;
246 int newlen;
247
248 newlen=strlen(str);
249 buffer=(char *)malloc(newlen+1);
250 if (!buffer) {
251 return NULL;
252 }
253 snprintf(buffer, newlen + 1, "%s", str);
254 return buffer;
255 }
256
d_cat(char * str1,char * str2)257 char *d_cat(char *str1, char *str2) {
258 int len1;
259 int len2;
260 char *buffer;
261
262 len1=strlen(str1);
263 len2=strlen(str2);
264 buffer=(char *)malloc(len1+len2+1);
265 if (!buffer) {
266 return NULL; /* Out-of-memory error */
267 }
268
269 snprintf(buffer, len1 + len2 + 1, "%s%s", str1, str2);
270 return buffer; /* and return the result! */
271 }
272
273 /* split line into two pieces. */
d_split(char * src,int ch)274 struct d_split_array *d_split(char *src, int ch) {
275 unsigned char c;
276 int i,n;
277 int len;
278
279 char *str1;
280 char *str2;
281 char *strptr;
282
283 struct d_split_array *retvalue;
284
285 len=strlen(src);
286 c=ch;
287 n=-1; /* guardian value. */
288 for (i=0;src[i];i++) {
289 if (src[i]==c) {
290 n=i;
291 break;
292 }
293 }
294 if (n==-1) {
295 return NULL; /* sorry, could not split on that character! */
296 }
297
298 str1=(char *) malloc(n+1); /* do the first string */
299 if (!str1) {
300 return NULL; /* could not malloc! */
301 }
302
303 for (i=0;i<n;i++) {
304 str1[i]=src[i];
305 }
306 str1[n]=0; /* chop off the trailing character! */
307
308 str2=(char *) malloc(len-n); /* for the rest... */
309 if (!str2) {
310 free(str1);
311 return NULL;
312 }
313 strptr=str2;
314 for (i=n+1;i<len;i++) {
315 *strptr++=src[i];
316 }
317 *strptr=0; /* and voila! */
318 /* now to malloc the return array: */
319 retvalue = (struct d_split_array *)malloc(sizeof(struct d_split_array));
320 if (!retvalue) { /* can't malloc! */
321 free(str1);
322 free(str2);
323 return NULL;
324 }
325 retvalue->str1=str1;
326 retvalue->str2=str2;
327 return retvalue;
328 }
329
330 /* Split a string into three pieces... */
d_split2(char * src,int ch)331 struct d_split2_array *d_split2(char *src, int ch)
332 {
333 struct d_split_array *d1;
334 struct d_split_array *d2;
335 struct d_split2_array *result;
336
337 d1=d_split(src,ch); /* do the first split */
338 if (!d1) {
339 return NULL; /* sorry! */
340 }
341 d2=d_split(d1->str2,ch); /* split the second half into two strings */
342 if (!d2) { /* un-leak memory, sigh */
343 free(d1->str1);
344 free(d1->str2);
345 free(d1);
346 return NULL;
347 }
348 /* we now have three strings, now to do something with them: */
349 result=(struct d_split2_array *)malloc(sizeof(struct d_split2_array));
350 if (!result) { /* arg, could not malloc! */
351 free(d1->str1);
352 free(d1->str2);
353 free(d1);
354 free(d2->str1);
355 free(d2->str2);
356 free(d2); /* maybe freed up enough memory? */
357 }
358 /* we malloced, now copy and free up other stuff: */
359 result->str1=d1->str1;
360 result->str2=d2->str1;
361 result->str3=d2->str2;
362 free(d1->str2); /* this was a temp string no longer needed */
363 free(d1);
364 free(d2);
365 return result;
366 }
367
368 #ifdef TEST_FUNCTION
369
main(void)370 void main(void) {
371 char *result;
372 char *dup;
373 char *trimmed;
374 char *dupdup;
375 struct d_split_array *ary1;
376
377 result=d_getline(stdin,1024);
378 trimmed=d_trim(result); /* trimm! */
379 dup=d_dup(trimmed);
380 printf("dup=%s\n",dup);
381 dupdup=d_cat(trimmed,dup);
382 printf("dupdup=%s\n",dupdup);
383 ary1=d_split(result,':');
384 printf("str1=%s str2=%s\n",ary1->str1,ary1->str2);
385 }
386
387 #endif
388
389
390
391