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