Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtsearchpath / libCliSrv / cstring.C
1 /* $XConsortium: cstring.C /main/2 1995/07/17 14:10:22 drk $ */
2 /*******************************************************************
3 **  (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
4 **  All rights are reserved.  Copying or other reproduction of this
5 **  program except for archival purposes is prohibited without prior
6 **  written consent of Hewlett-Packard Company.
7 ********************************************************************
8 ****************************<+>*************************************/
9
10 #include "cstring.h"
11 #include <ctype.h>
12
13 CString::CString()
14 {
15     contents = 0;
16     skipWhiteSpace = 1;
17 }
18
19 CString::CString
20         (
21         const char *  s,
22         unsigned char ws
23         ) : skipWhiteSpace(ws)
24 {
25     if (s != 0) {
26         contents = new char [strlen(s) + 1];
27         strcpy(contents,s);
28     }
29     else {
30         contents = new char [1];
31         strcpy(contents,"");
32     }
33
34 }
35
36 CString::CString
37         (
38         const char c,
39         unsigned char ws
40         ) : skipWhiteSpace(ws)
41 {
42     contents = new char [2];
43     contents[0] = c;
44     contents[1] = 0;
45 }
46
47 CString::~CString()
48 {
49     delete [] contents;
50 }
51
52 CString::CString
53         (
54         const CString & s
55         )
56 {
57     contents = new char [s.length() + 1];
58     strcpy(contents,s.data());
59     skipWhiteSpace = s.skipWhiteSpace;
60 }
61
62 char & CString::operator[]
63         (
64         int index
65         ) const
66 {
67     if (index < 0)
68         return contents[0];
69
70     if (index > strlen(contents))
71         return contents[strlen(contents)-1];
72
73     return contents[index];
74 }
75
76 int CString::operator!=
77         (
78         const CString & s
79         ) const
80 {
81     return !(*this == s);
82 }
83
84 int CString::operator==
85         (
86         const CString & s
87         ) const
88 {
89     if (isNull() && s.isNull())
90         return 1;
91
92     if (isNull() || s.isNull())
93         return 0;
94
95     if (strcmp(contents,s.data()) == 0)
96         return 1;
97
98     return 0;
99 }
100
101 CString & CString::operator=
102         (
103         const CString & s
104         )
105 {
106     if (s != *this) {
107         delete [] contents;
108         contents = new char [s.length() + 1];
109         strcpy(contents,s.data());
110     }
111     return *this;
112 }
113
114 CString & CString::operator=
115         (
116         const char * s
117         )
118 {
119     delete [] contents;
120     contents = new char [strlen(s) + 1];
121     strcpy(contents,s);
122     return *this;
123 }
124
125 CString & CString::operator+=
126         (
127         const char * cs
128         )
129 {
130 char * temp;
131
132     if (contents) {
133         if (cs)
134             temp = new char [strlen(contents) + strlen(cs) + 1];
135         else
136             return *this;
137     }
138     else {
139         if (cs)
140             temp = new char [strlen(cs) + 1];
141         else
142             return *this;
143     }
144
145     *temp = 0;
146     if (contents)
147         strcat(temp,contents);
148     if (cs)
149         strcat(temp,cs);
150
151     delete [] contents;
152     contents = temp;
153
154     return *this;
155 }
156
157
158 CString & CString::operator+= 
159         (
160         const CString & s
161         )
162 {
163 char * temp;
164
165     if (contents) {
166         if (s.contents)
167             temp = new char [strlen(contents) + s.length() + 1];
168         else
169             return *this;
170     }
171     else {
172         if (s.contents)
173             temp = new char [s.length() + 1];
174         else
175             return *this;
176     }
177
178     *temp = 0;
179     if (contents)
180         strcat(temp,contents);
181     if (s.contents)
182         strcat(temp,s.data());
183
184     delete [] contents;
185     contents = temp;
186
187     return *this;
188 }
189
190
191 CString operator+ 
192         (
193         const CString & s1, 
194         const CString & s2
195         )
196 {
197   CString result(s1);
198
199   result += s2;
200   return result;
201 }
202
203
204 CString operator+ 
205         (
206         const CString & s, 
207         const char * cs
208         )
209 {
210   CString result(s);
211
212   result += cs;
213   return result;
214 }
215
216
217 CString operator+ 
218         (
219         const char * cs, 
220         const CString & s
221         )
222 {
223   CString result(cs);
224
225   result += s;
226   return result;
227 }
228
229
230 CString CString::copy 
231         (
232         unsigned int start, 
233         const char * delim
234         )
235 {
236     if (isNull())
237         return *this;
238
239     for (int i = 0; i < strlen(delim); i++) {
240         char * q;
241         if (q = strchr(contents,delim[i])) {
242             char remember = *q;
243             *q = 0;
244             CString result(&contents[start]);
245             *q = remember;
246             return result;
247         }
248     }
249     return *this;
250 }
251
252 CString CString::copy 
253         (
254         const char * delim1, 
255         const char * delim2
256         )
257 {
258     if (isNull())
259         return *this;
260
261     for (int i = 0; i < strlen(delim1); i++) {
262         char * q;
263         if (q = strchr(contents,delim1[i])) {
264             for (int j = 0; j < strlen(delim2); j++) {
265                 char * p;
266                 if (p = strchr(q+1,delim2[j])) {
267                     char remember = *p;
268                     *p = 0;
269                     CString result(q+1);
270                     *p = remember;
271                     return result;
272                 }
273             }
274             return CString(q);
275         }
276     }
277     return *this;
278
279 }
280
281 CString CString::find 
282         (
283         const char * cs
284         )
285 {
286 char * q;
287
288     if (isNull())
289         return *this;
290
291     if (q = strstr(contents,cs))
292         return CString(q);
293
294     return *this;
295 }
296
297 int CString::contains 
298         (
299         const CString & s,
300         const char *    leader,
301         const char *    trailer
302         ) const
303 {
304     return contains(s.data(), leader, trailer);
305 }
306
307 int CString::contains 
308         (
309         const char * cs,
310         const char * leader,
311         const char * trailer
312         ) const
313 {
314     // first see if there is anything in contents
315
316     if (isNull())
317         return 0;
318
319     // or if the strings are exactly the same
320
321     if (strcmp(cs,data()) == 0)
322         return 1;
323
324     // now check to see if it is embedded in the string
325
326     CString search(leader);
327     search += cs;
328     search += trailer;
329
330     if (strstr (contents, search.data()))
331         return 1;
332
333     // if skipWhiteSpace is on then check for spaces on one or 
334     // both sides of the target in the source.
335
336     if (skipWhiteSpace) {
337
338         // first, a space in front, delimiter on the end
339
340         search = " ";
341         search += cs;
342         search += trailer;
343         if (strstr (contents, search.data()))
344             return 1;
345
346         // second, a delimiter on the front, space on the end
347
348         search = leader;
349         search += cs;
350         search += " ";
351         if (strstr (contents, search.data()))
352             return 1;
353
354         // third, spaces before and after
355
356         search = " ";
357         search += cs;
358         search += " ";
359         if (strstr (contents, search.data()))
360             return 1;
361     }
362
363     // now check to see if it is the start of the string
364
365     search = cs;
366     search += trailer;
367     if (strncmp (contents, search.data(), search.length()) == 0)
368         return 1;
369
370     // now check to see if it is the start of the string followed
371     // by a space
372
373     search = cs;
374     search += " ";
375     if (strncmp (contents, search.data(), search.length()) == 0)
376         return 1;
377
378     // last, check to see if it is on the end of the string using
379     // the delimiter and a space
380
381     search = leader;
382     while (1) {
383         search += cs;
384         char *q, *r = 0;
385         char *p = contents;
386         while (q = strstr(p, search.data())) {
387             r = q + strlen(leader);
388             p = q + 1;
389         }
390         if (r && strcmp(r,cs) == 0)
391             return 1;
392
393         if (search[0] == ' ')
394             break;
395
396         search = " ";
397     }
398
399     return 0;
400 }
401
402 void CString::replace
403         (
404         const CString & to_be_replaced,
405         const CString & replacee
406         )
407 {
408 char * q;
409
410     if (isNull())
411         return;
412
413     if (q = strstr(contents,to_be_replaced.data())) {
414         *q = 0;
415         char * prefix = new char [strlen(contents) + 1];
416         strcpy(prefix,contents);
417         q += to_be_replaced.length();
418         char * suffix = new char [strlen(q) + 1];
419         strcpy(suffix,q);
420         delete [] contents;
421         contents = new char [strlen(prefix) + 
422                              replacee.length() + 
423                              strlen(suffix) + 1];
424         strcpy(contents,prefix);
425         strcat(contents,replacee.data());
426         strcat(contents,suffix);
427         delete [] prefix;
428         delete [] suffix;
429     }
430 }
431
432 int CString::isNull() const
433 {
434     if (contents == 0)
435         return 1;
436
437     if (strlen(contents) == 0)
438         return 1;
439
440     return 0;
441 }
442
443
444 CTokenizedString::CTokenizedString()
445         : CString(""), finished(0), cursor(0), delimiter(0)
446 {}
447
448
449 CTokenizedString::CTokenizedString
450         (
451         const CTokenizedString & s
452         )
453 {
454   if (s != *this) {
455     cursor = new char [strlen(s.cursor) + 1];
456     strcpy(cursor,s.cursor);
457     delimiter = new char [strlen(s.delimiter) + 1];
458     strcpy(delimiter,s.delimiter);
459     finished = s.finished;
460     skipWhiteSpace = s.skipWhiteSpace;
461     contents = new char [strlen(s.contents) + 1];
462     strcpy(contents,s.contents);
463   }
464 }
465
466 CTokenizedString::CTokenizedString
467         (
468         const CString & s, 
469         char * d,
470         unsigned char ws
471         ) : CString(s), finished(0)
472 {
473     cursor = new char [s.length() + 1];
474     strcpy(cursor,s.data());
475     delimiter = new char [strlen(d) + 1];
476     strcpy(delimiter,d);
477     skipWhiteSpace = ws;
478 }
479
480
481 CTokenizedString::~CTokenizedString()
482 {
483     delete [] cursor;
484     delete [] delimiter;
485 }
486
487
488 CString CTokenizedString::next()
489 {
490 char * q  = 0;
491
492     if (cursor) {
493         if (strlen(delimiter) == 1)
494             q = strchr(cursor,delimiter[0]);
495         else {
496             for (int i = 0; i < strlen(cursor); i++)
497                 if (strchr(delimiter,cursor[i])) {
498                     q = &cursor[i];
499                     break;
500                 }
501         }
502     }
503
504     if (q) {
505
506         // a delimiter has been found. Create the return token,
507         // adjust the cursor
508
509         *q = 0;
510
511         // eliminate trailing white space
512
513         if (skipWhiteSpace) {
514             for (char *p = q; isspace(*(p-1)); p--);
515             *p = 0;
516         }
517         CString result(cursor);
518
519         // eliminate leading white space
520
521         if (skipWhiteSpace)
522             for (; isspace(*(q+1)); q++);
523
524         char * temp = new char [strlen(q+1) + 1];
525         strcpy(temp,q+1);
526         delete [] cursor;
527         cursor = temp;
528         return result;
529     }
530     else if (cursor) {
531
532         // no delimiter found. Return what is left of the string
533
534         CString result(cursor);
535         delete [] cursor;
536         cursor = 0;
537         return result;
538     }
539     else {
540         finished = 1;
541         return CString("");
542     }
543 }
544
545 ostream & operator<<
546         (
547         ostream &       os,
548         const CString & s
549         )
550 {
551     if (s.isNull())
552         return os << "(null)";
553
554     return os << s.data();
555 }