(file) Return to String.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2