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