1 mike 1.27 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 //==============================================================================
22 mike 1.27 //
23 // Author: Mike Brasher (mbrasher@bmc.com)
24 //
25 // Modified By:
26 //
27 //%/////////////////////////////////////////////////////////////////////////////
28
29
30 #include <cctype>
31 #include "String.h"
32 #include "Exception.h"
33 #include "String.h"
34 #include <iostream>
35
|
36 mike 1.28 PEGASUS_USING_STD;
37
|
38 mike 1.27 PEGASUS_NAMESPACE_BEGIN
39
40 #define PEGASUS_ARRAY_T String
41 #include <Pegasus/Common/ArrayImpl.h>
42 #undef PEGASUS_ARRAY_T
43
|
44 kumpf 1.37 const String String::EMPTY = String();
|
45 mike 1.27
|
46 kumpf 1.33 #if 0 // Apparently dead code
|
47 mike 1.27 static inline void _SkipWhitespace(const Char16*& p)
48 {
49 while (*p && isspace(*p))
50 p++;
51 }
|
52 kumpf 1.33 #endif
|
53 mike 1.27
|
54 kumpf 1.38 Uint32 _strnlen(const char* str, Uint32 n)
55 {
56 if (!str)
57 throw NullPointer();
58
59 for (Uint32 i=0; i<n; i++)
60 {
61 if (!*str)
62 {
63 return i;
64 }
65 }
66
67 return n;
68 }
69
70 Uint32 _strnlen(const Char16* str, Uint32 n)
71 {
72 if (!str)
73 throw NullPointer();
74
75 kumpf 1.38 for (Uint32 i=0; i<n; i++)
76 {
77 if (!*str)
78 {
79 return i;
80 }
81 }
82
83 return n;
84 }
85
|
86 mike 1.27 inline Uint32 StrLen(const char* str)
87 {
88 if (!str)
89 throw NullPointer();
90
91 return strlen(str);
92 }
93
94 inline Uint32 StrLen(const Char16* str)
95 {
96 if (!str)
97 throw NullPointer();
98
99 Uint32 n = 0;
100
101 while (*str++)
102 n++;
103
104 return n;
105 }
106
107 mike 1.27 String::String()
108 {
109 _rep.append('\0');
110 }
111
112 String::String(const String& x) : _rep(x._rep)
113 {
114
115 }
116
117 String::String(const String& x, Uint32 n)
118 {
|
119 kumpf 1.38 assign(x.getData(), n);
|
120 mike 1.27 }
121
122 String::String(const Char16* x) : _rep(x, StrLen(x) + 1)
123 {
124
125 }
126
127 String::String(const Char16* x, Uint32 n)
128 {
129 assign(x, n);
130 }
131
132 String::String(const char* str)
133 {
|
134 kumpf 1.38 assign(str);
|
135 mike 1.27 }
136
137 String::String(const char* str, Uint32 n_)
138 {
|
139 kumpf 1.38 assign(str, n_);
|
140 mike 1.27 }
141
142 String& String::assign(const Char16* x)
143 {
144 _rep.clear();
145 _rep.append(x, StrLen(x) + 1);
146 return *this;
147 }
148
149 String& String::assign(const Char16* str, Uint32 n)
150 {
151 _rep.clear();
|
152 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
153 mike 1.27 _rep.append(str, m);
154 _rep.append('\0');
155 return *this;
156 }
157
158 String& String::assign(const char* x)
159 {
160 _rep.clear();
|
161 kumpf 1.38
162 Uint32 n = strlen(x) + 1;
163 _rep.reserve(n);
|
164 mike 1.27
165 while (n--)
166 _rep.append(*x++);
167
168 return *this;
169 }
170
171 String& String::assign(const char* x, Uint32 n_)
172 {
173 _rep.clear();
174
|
175 kumpf 1.38 Uint32 n = _strnlen(x, n_);
|
176 mike 1.27 _rep.reserve(n + 1);
177
178 while (n--)
179 _rep.append(*x++);
180
181 _rep.append('\0');
182
183 return *this;
184 }
185
186 char* String::allocateCString(Uint32 extraBytes, Boolean noThrow) const
187 {
188 Uint32 n = size() + 1;
189 char* str = new char[n + extraBytes];
190 char* p = str;
191 const Char16* q = getData();
192
193 for (Uint32 i = 0; i < n; i++)
194 {
195 Uint16 c = *q++;
196 *p++ = char(c);
197 mike 1.27
198 if ((c & 0xff00) && !noThrow)
199 throw TruncatedCharacter();
200 }
201
202 return str;
203 }
204
205 void String::appendToCString(
206 char* str,
207 Uint32 length,
208 Boolean noThrow) const
209 {
210 if (!str)
211 throw NullPointer();
212
|
213 mike 1.31 Uint32 n = _pegasusMin(size(), length);
|
214 mike 1.27
215 char* p = str + strlen(str);
216 const Char16* q = getData();
217
218 for (Uint32 i = 0; i < n; i++)
219 {
220 Uint16 c = *q++;
221 *p++ = char(c);
222
223 if ((c & 0xff00) && !noThrow)
224 throw TruncatedCharacter();
225 }
226
227 *p = '\0';
228 }
229
230 Char16& String::operator[](Uint32 i)
231 {
232 if (i > size())
233 ThrowOutOfBounds();
234
235 mike 1.27 return _rep[i];
236 }
237
238 const Char16 String::operator[](Uint32 i) const
239 {
240 if (i > size())
241 ThrowOutOfBounds();
242
243 return _rep[i];
244 }
245
246 String& String::append(const Char16* str, Uint32 n)
247 {
|
248 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
249 mike 1.27 _rep.reserve(_rep.size() + m);
250 _rep.remove(_rep.size() - 1);
251 _rep.append(str, m);
252 _rep.append('\0');
253 return *this;
254 }
255
256 void String::remove(Uint32 pos, Uint32 size)
257 {
258 if (size == PEG_NOT_FOUND)
259 size = this->size() - pos;
260
261 if (pos + size > this->size())
262 ThrowOutOfBounds();
263
264 if (size)
265 _rep.remove(pos, size);
266 }
267
268 int String::compare(const Char16* s1, const Char16* s2, Uint32 n)
269 {
270 mike 1.27 while (n--)
271 {
272 int r = *s1++ - *s2++;
273
274 if (r)
275 return r;
276 }
277
278 return 0;
279 }
280
281 int String::compareNoCase(const char* s1, const char* s2, Uint32 n)
282 {
283 while (n--)
284 {
285 int r = tolower(*s1++) - tolower(*s2++);
286
287 if (r)
288 return r;
289 }
290
291 mike 1.27 return 0;
292 }
293
294 Boolean String::equal(const String& x, const String& y)
295 {
296 if (x.size() != y.size())
297 return false;
298
299 return String::compare(x.getData(), y.getData(), x.size()) == 0;
300 }
301
302 Boolean String::equal(const String& x, const Char16* y)
303 {
304 if (x.size() != StrLen(y))
305 return false;
306
307 return String::compare(x.getData(), y, x.size()) == 0;
308 }
309
310 Boolean String::equal(const Char16* x, const String& y)
311 {
312 mike 1.27 return equal(y, x);
313 }
314
315 Boolean String::equal(const String& x, const char* y)
316 {
317 return equal(x, String(y));
318 }
319
320 Boolean String::equal(const char* x, const String& y)
321 {
322 return equal(String(x), y);
323 }
324
325 Boolean String::equalNoCase(const String& x, const String& y)
326 {
327 if (x.size() != y.size())
328 return false;
329
330 const Char16* p = x.getData();
331 const Char16* q = y.getData();
332
333 mike 1.27 Uint32 n = x.size();
334
335 while (n--)
336 {
|
337 mike 1.30 #ifdef PEGASUS_HAS_EBCDIC
338 if (*p <= 255 && *q <= 255)
339 #else
|
340 mike 1.27 if (*p <= 127 && *q <= 127)
|
341 mike 1.30 #endif
|
342 mike 1.27 {
343 if (tolower(*p++) != tolower(*q++))
344 return false;
345 }
346 else if (*p++ != *q++)
347 return false;
348 }
349
350 return true;
351 }
352
353 String String::subString(Uint32 pos, Uint32 length) const
354 {
355 if (pos < size())
356 {
357 if (length == PEG_NOT_FOUND)
358 length = size() - pos;
359
360 return String(getData() + pos, length);
361 }
362 else
363 mike 1.27 return String();
364 }
365
366 Uint32 String::find(Char16 c) const
367 {
368 const Char16* first = getData();
369
370 for (const Char16* p = first; *p; p++)
371 {
372 if (*p == c)
373 return p - first;
374 }
375
376 return PEG_NOT_FOUND;
377 }
378
|
379 mike 1.30 Uint32 String::find(Uint32 pos, Char16 c) const
380 {
381 const Char16* data = getData();
382
383 for (Uint32 i = pos, n = size(); i < n; i++)
384 {
385 if (data[i] == c)
386 return i;
387 }
388
389 return PEG_NOT_FOUND;
390 }
391
|
392 mike 1.27 Uint32 String::find(const String& s) const
393 {
394 const Char16* pSubStr = s.getData();
395 const Char16* pStr = getData();
396 Uint32 subStrLen = s.size();
397 Uint32 strLen = size();
398
|
399 mike 1.30 if (subStrLen > strLen)
400 {
401 return PEG_NOT_FOUND;
402 }
403
|
404 mike 1.27 // loop to find first char match
405 Uint32 loc = 0;
406 for( ; loc <= (strLen-subStrLen); loc++)
407 {
408 if (*pStr++ == *pSubStr) // match first char
409 {
410 // point to substr 2nd char
411 const Char16* p = pSubStr + 1;
412
413 // Test remaining chars for equal
414 Uint32 i = 1;
415 for (; i < subStrLen; i++)
416 if (*pStr++ != *p++ )
417 {pStr--; break;} // break from loop
418 if (i == subStrLen)
419 return loc;
420 }
421 }
422 return PEG_NOT_FOUND;
423 }
424
425 mike 1.27 Uint32 String::find(const char* s) const
|
426 kumpf 1.33 {
427 return find(String(s));
428 }
429
430 Uint32 String::find(const Char16* s) const
|
431 mike 1.27 {
432 return find(String(s));
433 }
434
435 Uint32 String::reverseFind(Char16 c) const
436 {
437 const Char16* first = getData();
438 const Char16* last = getData() + size();
439
440 while (last != first)
441 {
442 if (*--last == c)
443 return last - first;
444 }
445
446 return PEG_NOT_FOUND;
447 }
448
449 void String::toLower()
450 {
451 for (Char16* p = &_rep[0]; *p; p++)
452 mike 1.27 {
|
453 mike 1.30 #ifdef PEGASUS_HAS_EBCDIC
454 if (*p <= 255)
455 #else
|
456 mike 1.27 if (*p <= 127)
|
457 mike 1.30 #endif
|
458 mike 1.27 *p = tolower(*p);
459 }
460 }
461
462 void String::translate(Char16 fromChar, Char16 toChar)
463 {
464 for (Char16* p = &_rep[0]; *p; p++)
465 {
466 if (*p == fromChar)
467 *p = toChar;
468 }
469 }
470
471 int String::compare(const Char16* s1, const Char16* s2)
472 {
473 while (*s1 && *s2)
474 {
475 int r = *s1++ - *s2++;
476
477 if (r)
478 return r;
479 mike 1.27 }
480
481 if (*s2)
482 return -1;
483 else if (*s1)
484 return 1;
485
486 return 0;
487 }
488
|
489 mike 1.30 int String::compareNoCase(const char* s1, const char* s2)
490 {
491 while (*s1 && *s2)
492 {
493 int r = tolower(*s1++) - tolower(*s2++);
494
495 if (r)
496 return r;
497 }
498
499 if (*s2)
500 return -1;
501 else if (*s1)
502 return 1;
503
504 return 0;
505 }
506
|
507 mike 1.27 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& x)
508 {
509 for (Uint32 i = 0, n = x.size(); i < n; i++)
510 os << x[i];
511
512 return os;
513 }
514
515 void String::toLower(char* str)
516 {
517 while (*str)
518 tolower(*str++);
519 }
520
521 String ToLower(const String& str)
522 {
523 String tmp(str);
524
525 for (Uint32 i = 0, n = tmp.size(); i < n; i++)
526 {
527 Char16 c = tmp[i];
528 mike 1.27
|
529 mike 1.30 #ifdef PEGASUS_HAS_EBCDIC
530 if (c <= 255)
531 #else
|
532 mike 1.27 if (c <= 127)
|
533 mike 1.30 #endif
|
534 mike 1.27 tmp[i] = tolower(c);
535 }
536
537 return tmp;
538 }
539
540 int CompareNoCase(const char* s1, const char* s2)
541 {
542 while (*s1 && *s2)
543 {
544 int r = tolower(*s1++) - tolower(*s2++);
545
546 if (r)
547 return r;
548 }
549
550 if (*s2)
551 return -1;
552 else if (*s1)
553 return 1;
554
555 mike 1.27 return 0;
556 }
557
558 Boolean GetLine(PEGASUS_STD(istream)& is, String& line)
559 {
560 line.clear();
561
562 Boolean gotChar = false;
563 char c;
564
565 while (is.get(c))
566 {
567 gotChar = true;
568
569 if (c == '\n')
570 break;
571
572 line.append(c);
573 }
574
575 return gotChar;
576 mike 1.27 }
577
578 String::~String()
579 {
580 }
581
582 String& String::assign(const String& x)
583 {
584 _rep = x._rep;
585 return *this;
586 }
587
588 String& String::append(const Char16& c)
589 {
590 _rep.insert(_rep.size() - 1, c);
591 return *this;
592 }
593
594 void String::clear()
595 {
596 _rep.clear();
597 mike 1.27 _rep.append('\0');
598 }
599
|
600 mike 1.28 void String::print() const
601 {
602 cout << *this << endl;
603 }
604
|
605 mike 1.27 void String::reserve(Uint32 capacity)
606 {
607 _rep.reserve(capacity + 1);
608 }
609
610 const Array<String>& EmptyStringArray()
611 {
612 static Array<String> tmp;
613 return tmp;
614 }
|
615 karl 1.36 //#define NEWMATCHFUNCTION
616 #if defined NEWMATCHFUNCTION
617 // Wildcard String matching function that may be useful in the future
618 // The following code was provided by Bob Blair.
619
620 /* _StringMatch Match input MatchString against a GLOB style pattern
621 Note that MatchChar is the char type so that this source
622 in portable to different string types. This is an internal function
623
624 Results: The return value is 1 if string matches pattern, and
625 0 otherwise. The matching operation permits the following
626 special characters in the pattern: *?\[] (see the manual
627 entry for details on what these mean).
628
629 Side effects: None.
630 */
631
632 /* MatchChar defined as a separate entity because this function source used
633 elsewhere was an unsigned char *. Here we use Uint16 to maintain 16 bit
634 size.
635 */
636 karl 1.36 typedef Uint16 MatchChar;
637
638 inline Uint16 _ToLower(Uint16 ch)
639 {
640 #ifdef PEGASUS_HAS_EBCDIC
641 return ch <= 255 ? tolower(char(ch)) : ch;
642 #else
643 return ch <= 127 ? tolower(char(ch)) : ch;
644 #endif
645 }
646
647 inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
648 {
649 if (nocase)
650 return _ToLower(ch1) == _ToLower(ch2);
651 else
652 return ch1 == ch2;
653 }
|
654 mike 1.28
|
655 kumpf 1.35
|
656 karl 1.36 static const MatchChar *
657 _matchrange(const MatchChar *range, MatchChar c, int nocase)
658 {
659 const MatchChar *p = range;
660 const MatchChar *rstart = range + 1;
661 const MatchChar *rend = 0;
662 MatchChar compchar;
663
|
664 kumpf 1.35 for (rend = rstart; *rend && *rend != ']'; rend++);
|
665 karl 1.36 if (*rend == ']') { // if there is an end to this pattern
|
666 kumpf 1.35 for (compchar = *rstart; rstart != rend; rstart++) {
|
667 karl 1.36 if (_Equal(*rstart, c, nocase))
|
668 kumpf 1.35 return ++rend;
669 if (*rstart == '-') {
670 rstart++;
671 if (c >= compchar && c <= *rstart)
672 return ++rend;
673 }
674 }
675 }
|
676 karl 1.36 return (const MatchChar *)0;
|
677 kumpf 1.35 }
678
679 static int
|
680 karl 1.36 _StringMatch(
681 const MatchChar *testString,
682 const MatchChar *pattern,
683 int nocase ) /* Ignore case if this is true */
684 {
685 const MatchChar *pat = pattern;
686 const MatchChar *str = testString;
|
687 kumpf 1.35 unsigned int done = 0;
688 unsigned int res = 0; // the result: 1 == match
689
690 while (!done) { // main loop walks through pattern and test string
691 //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
692 if (!*pat) { //end of pattern
693 done = 1; // we're done
694 if (!*str) //end of test, too?
695 res = 1; // then we matched
696 } else { //Not end of pattern
697 if (!*str) { // but end of test
698 done = 1; // We're done
699 if (*pat == '*') // If pattern openends
700 res = 1; // then we matched
701 } else { //Not end of test
702 if (*pat == '*') { //Ambiguuity found
703 if (!*++pat) { //and it ends pattern
704 done = 1; // then we're done
705 res = 1; // and match
706 } else { //if it doesn't end
707 while (!done) { // until we're done
|
708 karl 1.36 if (_StringMatch(str, pat, nocase)) { // we recurse
|
709 kumpf 1.35 done = 1; //if it recurses true
710 res = 1; // we done and match
711 } else { //it recurses false
712 if (!*str) // see if test is done
713 done = 1; // yes: we done
714 else // not done:
715 str++; // keep testing
716 } // end test on recursive call
717 } // end looping on recursive calls
718 } // end logic when pattern is ambiguous
719 } else { //pattern not ambiguus
720 if (*pat == '?') { //pattern is 'any'
721 pat++, str++; // so move along
722 } else if (*pat == '[') { //see if it's a range
|
723 karl 1.36 pat = _matchrange(pat, *str, nocase); // and is a match
|
724 kumpf 1.35 if (!pat) { //It is not a match
725 done = 1; // we're done
726 res = 1; // no match
727 } else { //Range matches
728 str++, pat++; // keep going
729 }
730 } else { // only case left is individual characters
|
731 karl 1.36 if (!_Equal(*pat++, *str++, nocase)) // if they don't match
|
732 kumpf 1.35 done = 1; // bail.
733 }
734 } // end ("pattern is not ambiguous (*)" logic
735 } // end logic when pattern and string still have data
736 } // end logic when pattern still has data
737 } // end main loop
738 return res;
739 }
740
|
741 karl 1.36 #else
742 ////////////////////////////////////////////////////////////////////////////////
743 //
744 // String matching routines borrowed from Tcl 8.0:
745 //
746 ////////////////////////////////////////////////////////////////////////////////
747
748 ////////////////////////////////////////////////////////////////////////////////
749 //
750 // This software is copyrighted by the Regents of the University of
751 // California, Sun Microsystems, Inc., and other parties. The following
752 // terms apply to all files associated with the software unless explicitly
753 // disclaimed in individual files.
754 //
755 // The authors hereby grant permission to use, copy, modify, distribute,
756 // and license this software and its documentation for any purpose, provided
757 // that existing copyright notices are retained in all copies and that this
758 // notice is included verbatim in any distributions. No written agreement,
759 // license, or royalty fee is required for any of the authorized uses.
760 // Modifications to this software may be copyrighted by their authors
761 // and need not follow the licensing terms described here, provided that
762 karl 1.36 // the new terms are clearly indicated on the first page of each file where
763 // they apply.
764 //
765 // IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
766 // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
767 // ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
768 // DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
769 // POSSIBILITY OF SUCH DAMAGE.
770 //
771 // THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
772 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
773 // FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
774 // IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
775 // NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
776 // MODIFICATIONS.
777 //
778 // GOVERNMENT USE: If you are acquiring this software on behalf of the
779 // U.S. government, the Government shall have only "Restricted Rights"
780 // in the software and related documentation as defined in the Federal
781 // Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
782 // are acquiring the software on behalf of the Department of Defense, the
783 karl 1.36 // software shall be classified as "Commercial Computer Software" and the
784 // Government shall have only "Restricted Rights" as defined in Clause
785 // 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
786 // authors grant the U.S. Government and others acting in its behalf
787 // permission to use and distribute the software in accordance with the
788 // terms specified in this license.
789 //
790 ////////////////////////////////////////////////////////////////////////////////
791
792
793 /*
794 *----------------------------------------------------------------------
795 *
796 * Tcl_StringMatch --
797 *
798 * See if a particular string matches a particular pattern.
799 *
800 * Results:
801 * The return value is 1 if string matches pattern, and
802 * 0 otherwise. The matching operation permits the following
803 * special characters in the pattern: *?\[] (see the manual
804 karl 1.36 * entry for details on what these mean).
805 *
806 * Side effects:
807 * None.
808 *
809 *----------------------------------------------------------------------
810 */
811
812 typedef Uint16 MatchChar;
813
814 inline Uint16 _ToLower(Uint16 ch)
815 {
816 #ifdef PEGASUS_HAS_EBCDIC
817 return ch <= 255 ? tolower(char(ch)) : ch;
818 #else
819 return ch <= 127 ? tolower(char(ch)) : ch;
820 #endif
821 }
822
823 inline Boolean _Equal(Uint16 ch1, Uint16 ch2, int nocase)
824 {
825 karl 1.36 if (nocase)
826 return _ToLower(ch1) == _ToLower(ch2);
827 else
828 return ch1 == ch2;
829 }
830
831 int _StringMatch(
832 MatchChar *string, /* String. */
833 MatchChar *pattern, /* Pattern, which may contain special
834 * characters. */
835 int nocase) /* Ignore case if this is true */
836 {
837 MatchChar c2;
838
839 while (1) {
840 /* See if we're at the end of both the pattern and the string.
841 * If so, we succeeded. If we're at the end of the pattern
842 * but not at the end of the string, we failed.
843 */
844
845 if (*pattern == 0) {
846 karl 1.36 if (*string == 0) {
847 return 1;
848 } else {
849 return 0;
850 }
851 }
852 if ((*string == 0) && (*pattern != '*')) {
853 return 0;
854 }
855
856 /* Check for a "*" as the next pattern character. It matches
857 * any substring. We handle this by calling ourselves
858 * recursively for each postfix of string, until either we
859 * match or we reach the end of the string.
860 */
861
862 if (*pattern == '*') {
863 pattern += 1;
864 if (*pattern == 0) {
865 return 1;
866 }
867 karl 1.36 while (1) {
868 if (_StringMatch(string, pattern, nocase)) {
869 return 1;
870 }
871 if (*string == 0) {
872 return 0;
873 }
874 string += 1;
875 }
876 }
877
878 /* Check for a "?" as the next pattern character. It matches
879 * any single character.
880 */
881
882 if (*pattern == '?') {
883 goto thisCharOK;
884 }
885
886 /* Check for a "[" as the next pattern character. It is followed
887 * by a list of characters that are acceptable, or by a range
888 karl 1.36 * (two characters separated by "-").
889 */
890
891 if (*pattern == '[') {
892 pattern += 1;
893 while (1) {
894 if ((*pattern == ']') || (*pattern == 0)) {
895 return 0;
896 }
897 if (_Equal(*pattern, *string, nocase)) {
898 break;
899 }
900 if (pattern[1] == '-') {
901 c2 = pattern[2];
902 if (c2 == 0) {
903 return 0;
904 }
905 if ((*pattern <= *string) && (c2 >= *string)) {
906 break;
907 }
908 if ((*pattern >= *string) && (c2 <= *string)) {
909 karl 1.36 break;
910 }
911 pattern += 2;
912 }
913 pattern += 1;
914 }
915 while (*pattern != ']') {
916 if (*pattern == 0) {
917 pattern--;
918 break;
919 }
920 pattern += 1;
921 }
922 goto thisCharOK;
923 }
924
925 /* If the next pattern character is '/', just strip off the '/'
926 * so we do exact matching on the character that follows.
927 */
928
929 if (*pattern == '\\') {
930 karl 1.36 pattern += 1;
931 if (*pattern == 0) {
932 return 0;
933 }
934 }
935
936 /* There's no special character. Just make sure that the next
937 * characters of each string match.
938 */
939
940 if (!_Equal(*pattern, *string, nocase)) {
941 return 0;
942 }
943
944 thisCharOK: pattern += 1;
945 string += 1;
946 }
|
947 kumpf 1.35 }
948 #endif
|
949 karl 1.36 Boolean String::match(const String& str, const String& pattern)
950 {
951 return _StringMatch(
952 (Uint16*)str.getData(), (Uint16*)pattern.getData(), 0) != 0;
953 }
954
955 Boolean String::matchNoCase(const String& str, const String& pattern)
956 {
957 return _StringMatch(
958 (Uint16*)str.getData(), (Uint16*)pattern.getData(), 1) != 0;
959 }
|
960 kumpf 1.35
|
961 mike 1.27 PEGASUS_NAMESPACE_END
|