(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            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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2