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

  1 mike  1.27 //%/////////////////////////////////////////////////////////////////////////////
  2            //
  3 kumpf 1.41 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
  4            // The Open Group, Tivoli Systems
  5 mike  1.27 //
  6            // Permission is hereby granted, free of charge, to any person obtaining a copy
  7 kumpf 1.41 // of this software and associated documentation files (the "Software"), to
  8            // deal in the Software without restriction, including without limitation the
  9            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10 mike  1.27 // sell copies of the Software, and to permit persons to whom the Software is
 11            // furnished to do so, subject to the following conditions:
 12            // 
 13 kumpf 1.41 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 14 mike  1.27 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 15            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 16 kumpf 1.41 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 17            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 18            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 19 mike  1.27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 20            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 21            //
 22            //==============================================================================
 23            //
 24            // Author: Mike Brasher (mbrasher@bmc.com)
 25            //
 26 kumpf 1.39 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 27 mike  1.27 //
 28            //%/////////////////////////////////////////////////////////////////////////////
 29            
 30            
 31            #include <cctype>
 32            #include "String.h"
 33 kumpf 1.43 #include "Array.h"
 34 kumpf 1.48 #include "InternalException.h"
 35 mike  1.27 #include <iostream>
 36            
 37 mike  1.28 PEGASUS_USING_STD;
 38            
 39 mike  1.27 PEGASUS_NAMESPACE_BEGIN
 40            
 41 kumpf 1.39 ///////////////////////////////////////////////////////////////////////////////
 42            //
 43            // String
 44            //
 45            ///////////////////////////////////////////////////////////////////////////////
 46            
 47 kumpf 1.37 const String String::EMPTY = String();
 48 mike  1.27 
 49 kumpf 1.38 Uint32 _strnlen(const char* str, Uint32 n)
 50            {
 51                if (!str)
 52            	throw NullPointer();
 53            
 54                for (Uint32 i=0; i<n; i++)
 55                {
 56                    if (!*str)
 57                    {
 58                        return i;
 59                    }
 60                }
 61            
 62                return n;
 63            }
 64            
 65            Uint32 _strnlen(const Char16* str, Uint32 n)
 66            {
 67                if (!str)
 68            	throw NullPointer();
 69            
 70 kumpf 1.38     for (Uint32 i=0; i<n; i++)
 71                {
 72                    if (!*str)
 73                    {
 74                        return i;
 75                    }
 76                }
 77            
 78                return n;
 79            }
 80            
 81 kumpf 1.39 inline Uint32 _StrLen(const char* str)
 82 mike  1.27 {
 83                if (!str)
 84            	throw NullPointer();
 85            
 86                return strlen(str);
 87            }
 88            
 89 kumpf 1.39 inline Uint32 _StrLen(const Char16* str)
 90 mike  1.27 {
 91                if (!str)
 92            	throw NullPointer();
 93            
 94                Uint32 n = 0;
 95            
 96                while (*str++)
 97            	n++;
 98            
 99                return n;
100            }
101            
102 kumpf 1.43 class StringRep
103            {
104            public:
105                StringRep()
106                {}
107                StringRep(const StringRep& r)
108                    : c16a(r.c16a)
109                {}
110                StringRep(const Char16* str)
111                    : c16a(str, _StrLen(str) + 1)
112                {}
113            
114                Array<Char16> c16a;
115            };
116            
117 mike  1.27 String::String()
118            {
119 kumpf 1.43     _rep = new StringRep;
120                _rep->c16a.append('\0');
121 mike  1.27 }
122            
123 kumpf 1.39 String::String(const String& str)
124 mike  1.27 {
125 kumpf 1.43     _rep = new StringRep(*str._rep);
126 kumpf 1.39 }
127 mike  1.27 
128 kumpf 1.39 String::String(const String& str, Uint32 n)
129            {
130 kumpf 1.43     _rep = new StringRep;
131 kumpf 1.39     assign(str.getData(), n);
132            }
133            
134            String::String(const Char16* str)
135            {
136 kumpf 1.43     _rep = new StringRep(str);
137 mike  1.27 }
138            
139 kumpf 1.39 String::String(const Char16* str, Uint32 n)
140            {
141 kumpf 1.43     _rep = new StringRep;
142 kumpf 1.39     assign(str, n);
143            }
144            
145            String::String(const char* str)
146 mike  1.27 {
147 kumpf 1.43     _rep = new StringRep;
148 kumpf 1.39     assign(str);
149 mike  1.27 }
150            
151 kumpf 1.39 String::String(const char* str, Uint32 n)
152 mike  1.27 {
153 kumpf 1.43     _rep = new StringRep;
154 kumpf 1.39     assign(str, n);
155            }
156 mike  1.27 
157 kumpf 1.39 String::~String()
158            {
159 kumpf 1.43     delete _rep;
160 mike  1.27 }
161            
162 kumpf 1.39 String& String::operator=(const String& str)
163 mike  1.27 {
164 kumpf 1.39     return assign(str);
165 mike  1.27 }
166            
167 kumpf 1.39 String& String::assign(const String& str)
168 mike  1.27 {
169 kumpf 1.43     _rep->c16a = str._rep->c16a;
170 kumpf 1.39     return *this;
171 mike  1.27 }
172            
173 kumpf 1.39 String& String::assign(const Char16* str)
174 mike  1.27 {
175 kumpf 1.43     _rep->c16a.clear();
176                _rep->c16a.append(str, _StrLen(str) + 1);
177 mike  1.27     return *this;
178            }
179            
180            String& String::assign(const Char16* str, Uint32 n)
181            {
182 kumpf 1.43     _rep->c16a.clear();
183 kumpf 1.38     Uint32 m = _strnlen(str, n);
184 kumpf 1.43     _rep->c16a.append(str, m);
185                _rep->c16a.append('\0');
186 mike  1.27     return *this;
187            }
188            
189 kumpf 1.39 String& String::assign(const char* str)
190 mike  1.27 {
191 kumpf 1.43     _rep->c16a.clear();
192 kumpf 1.38 
193 kumpf 1.39     Uint32 n = strlen(str) + 1;
194 kumpf 1.45     _rep->c16a.reserveCapacity(n);
195 mike  1.27 
196                while (n--)
197 kumpf 1.43 	_rep->c16a.append(*str++);
198 mike  1.27 
199                return *this;
200            }
201            
202 kumpf 1.39 String& String::assign(const char* str, Uint32 n)
203 mike  1.27 {
204 kumpf 1.43     _rep->c16a.clear();
205 mike  1.27 
206 kumpf 1.39     Uint32 _n = _strnlen(str, n);
207 kumpf 1.45     _rep->c16a.reserveCapacity(_n + 1);
208 mike  1.27 
209 kumpf 1.39     while (_n--)
210 kumpf 1.43 	_rep->c16a.append(*str++);
211 mike  1.27 
212 kumpf 1.43     _rep->c16a.append('\0');
213 mike  1.27 
214                return *this;
215            }
216            
217 kumpf 1.39 void String::clear()
218            {
219 kumpf 1.43     _rep->c16a.clear();
220                _rep->c16a.append('\0');
221 kumpf 1.39 }
222            
223 kumpf 1.43 void String::reserveCapacity(Uint32 capacity)
224 kumpf 1.39 {
225 kumpf 1.45     _rep->c16a.reserveCapacity(capacity + 1);
226 kumpf 1.39 }
227            
228            Uint32 String::size() const
229            {
230 kumpf 1.43     return _rep->c16a.size() - 1;
231 kumpf 1.39 }
232            
233            const Char16* String::getData() const
234            {
235 kumpf 1.43     return _rep->c16a.getData();
236 kumpf 1.39 }
237            
238 kumpf 1.49 char* String::allocateCString(Uint32 extraBytes, Boolean& truncatedCharacters) const
239 mike  1.27 {
240 kumpf 1.49     truncatedCharacters = false;
241 mike  1.27     Uint32 n = size() + 1;
242                char* str = new char[n + extraBytes];
243                char* p = str;
244                const Char16* q = getData();
245            
246                for (Uint32 i = 0; i < n; i++)
247                {
248            	Uint16 c = *q++;
249            	*p++ = char(c);
250            
251 kumpf 1.49 	if (c & 0xff00)
252            	    truncatedCharacters = true;
253 mike  1.27     }
254            
255                return str;
256            }
257            
258 kumpf 1.49 char* String::allocateCString(Uint32 extraBytes) const
259            {
260                Boolean truncatedCharacters = false;
261                return allocateCString(extraBytes, truncatedCharacters);
262            }
263            
264 mike  1.27 Char16& String::operator[](Uint32 i)
265            {
266                if (i > size())
267 kumpf 1.49 	throw IndexOutOfBoundsException();
268 mike  1.27 
269 kumpf 1.43     return _rep->c16a[i];
270 mike  1.27 }
271            
272            const Char16 String::operator[](Uint32 i) const
273            {
274                if (i > size())
275 kumpf 1.49 	throw IndexOutOfBoundsException();
276 mike  1.27 
277 kumpf 1.43     return _rep->c16a[i];
278 mike  1.27 }
279            
280 kumpf 1.39 String& String::append(const Char16& c)
281            {
282 kumpf 1.43     _rep->c16a.insert(_rep->c16a.size() - 1, c);
283 kumpf 1.39     return *this;
284            }
285            
286 mike  1.27 String& String::append(const Char16* str, Uint32 n)
287            {
288 kumpf 1.38     Uint32 m = _strnlen(str, n);
289 kumpf 1.45     _rep->c16a.reserveCapacity(_rep->c16a.size() + m);
290 kumpf 1.43     _rep->c16a.remove(_rep->c16a.size() - 1);
291                _rep->c16a.append(str, m);
292                _rep->c16a.append('\0');
293 mike  1.27     return *this;
294            }
295            
296 kumpf 1.39 String& String::append(const String& str)
297 mike  1.27 {
298 kumpf 1.39     return append(str.getData(), str.size());
299 mike  1.27 }
300            
301 kumpf 1.39 void String::remove(Uint32 pos, Uint32 size)
302 mike  1.27 {
303 kumpf 1.39     if (size == PEG_NOT_FOUND)
304            	size = this->size() - pos;
305 mike  1.27 
306 kumpf 1.39     if (pos + size > this->size())
307 kumpf 1.49 	throw IndexOutOfBoundsException();
308 mike  1.27 
309 kumpf 1.39     if (size)
310 kumpf 1.43 	_rep->c16a.remove(pos, size);
311 mike  1.27 }
312            
313            String String::subString(Uint32 pos, Uint32 length) const
314            {
315                if (pos < size())
316                {
317            	if (length == PEG_NOT_FOUND)
318            	    length = size() - pos;
319            
320            	return String(getData() + pos, length);
321                }
322                else
323            	return String();
324            }
325            
326            Uint32 String::find(Char16 c) const
327            {
328                const Char16* first = getData();
329            
330                for (const Char16* p = first; *p; p++)
331                {
332 mike  1.27 	if (*p == c)
333            	    return  p - first;
334                }
335            
336                return PEG_NOT_FOUND;
337            }
338            
339 mike  1.30 Uint32 String::find(Uint32 pos, Char16 c) const
340            {
341                const Char16* data = getData();
342            
343                for (Uint32 i = pos, n = size(); i < n; i++)
344                {
345            	if (data[i] == c)
346            	    return i;
347                }
348            
349                return PEG_NOT_FOUND;
350            }
351            
352 mike  1.27 Uint32 String::find(const String& s) const
353            {
354                const Char16* pSubStr = s.getData();
355                const Char16* pStr = getData();
356                Uint32 subStrLen = s.size();
357                Uint32 strLen = size();
358            
359 mike  1.30     if (subStrLen > strLen)
360                {
361                    return PEG_NOT_FOUND;
362                }
363            
364 mike  1.27     // loop to find first char match
365                Uint32 loc = 0;
366                for( ; loc <= (strLen-subStrLen); loc++)
367                {
368            	if (*pStr++ == *pSubStr)  // match first char
369            	{
370            	    // point to substr 2nd char
371            	    const Char16* p = pSubStr + 1;
372            
373            	    // Test remaining chars for equal
374            	    Uint32 i = 1;
375            	    for (; i < subStrLen; i++)
376            		if (*pStr++ != *p++ )
377            		    {pStr--; break;} // break from loop
378            	    if (i == subStrLen)
379            		return loc;
380            	}
381                }
382                return PEG_NOT_FOUND;
383            }
384            
385 mike  1.27 Uint32 String::reverseFind(Char16 c) const
386            {
387                const Char16* first = getData();
388                const Char16* last = getData() + size();
389            
390                while (last != first)
391                {
392            	if (*--last == c)
393            	    return last - first;
394                }
395            
396                return PEG_NOT_FOUND;
397            }
398            
399            void String::toLower()
400            {
401 kumpf 1.43     for (Char16* p = &_rep->c16a[0]; *p; p++)
402 mike  1.27     {
403 kumpf 1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
404 mike  1.27 	    *p = tolower(*p);
405                }
406 kumpf 1.39 }
407            
408 kumpf 1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
409 kumpf 1.39 {
410 kumpf 1.43     const Char16* s1c16 = s1.getData();
411                const Char16* s2c16 = s2.getData();
412 kumpf 1.39 
413                while (n--)
414 mike  1.27     {
415 kumpf 1.43 	int r = *s1c16++ - *s2c16++;
416 mike  1.27 
417            	if (r)
418            	    return r;
419                }
420            
421                return 0;
422            }
423            
424 kumpf 1.43 int String::compare(const String& s1, const String& s2)
425 mike  1.30 {
426 kumpf 1.43     const Char16* s1c16 = s1.getData();
427                const Char16* s2c16 = s2.getData();
428            
429                while (*s1c16 && *s2c16)
430 mike  1.30     {
431 kumpf 1.43 	int r = *s1c16++ - *s2c16++;
432 mike  1.30 
433            	if (r)
434            	    return r;
435                }
436            
437 kumpf 1.43     if (*s2c16)
438 mike  1.30 	return -1;
439 kumpf 1.43     else if (*s1c16)
440 mike  1.30 	return 1;
441            
442                return 0;
443            }
444            
445 kumpf 1.40 int String::compareNoCase(const String& s1, const String& s2)
446            {
447                const Char16* _s1 = s1.getData();
448                const Char16* _s2 = s2.getData();
449            
450                while (*_s1 && *_s2)
451                {
452                    int r;
453            
454 kumpf 1.46         if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
455                        *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
456 kumpf 1.40         {
457                        r = tolower(*_s1++) - tolower(*_s2++);
458                    }
459                    else
460                    {
461                        r = *_s1++ - *_s2++;
462                    }
463            
464            	if (r)
465            	    return r;
466                }
467            
468                if (*_s2)
469            	return -1;
470                else if (*_s1)
471            	return 1;
472            
473                return 0;
474            }
475            
476 kumpf 1.39 Boolean String::equal(const String& str1, const String& str2)
477 mike  1.27 {
478 kumpf 1.43     return String::compare(str1, str2) == 0;
479 mike  1.27 }
480            
481 kumpf 1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
482 mike  1.27 {
483 kumpf 1.39     if (str1.size() != str2.size())
484            	return false;
485            
486                const Char16* p = str1.getData();
487                const Char16* q = str2.getData();
488            
489                Uint32 n = str1.size();
490 mike  1.27 
491 kumpf 1.39     while (n--)
492                {
493 kumpf 1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
494                        *q <= PEGASUS_MAX_PRINTABLE_CHAR)
495 kumpf 1.39 	{
496            	    if (tolower(*p++) != tolower(*q++))
497            		return false;
498            	}
499            	else if (*p++ != *q++)
500            	    return false;
501                }
502 mike  1.28 
503 kumpf 1.39     return true;
504 mike  1.27 }
505            
506 kumpf 1.42 
507            // ATTN-RK-P3-20020603: This code is not completely correct
508 karl  1.36  // Wildcard String matching function that may be useful in the future
509            // The following code was provided by Bob Blair.
510            
511            /* _StringMatch Match input MatchString against a GLOB style pattern
512                   Note that MatchChar is the char type so that this source
513                   in portable to different string types. This is an internal function
514             
515              Results: The return value is 1 if string matches pattern, and
516             	0 otherwise.  The matching operation permits the following
517             	special characters in the pattern: *?\[] (see the manual
518             	entry for details on what these mean).
519             
520              Side effects: None.
521             */
522            
523            /* MatchChar defined as a separate entity because this function source used
524                elsewhere was an unsigned char *. Here we use Uint16 to  maintain 16 bit 
525                size.
526            */
527            typedef Uint16 MatchChar;
528            
529 karl  1.36 inline Uint16 _ToLower(Uint16 ch)
530            {
531 kumpf 1.46     return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
532 karl  1.36 }
533            
534            inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
535            {
536                if (nocase)
537            	return _ToLower(ch1) == _ToLower(ch2);
538                else
539            	return ch1 == ch2;
540            }
541 mike  1.28 
542 kumpf 1.35 
543 karl  1.36 static const MatchChar *
544            _matchrange(const MatchChar *range, MatchChar c, int nocase)
545            {
546              const MatchChar *p = range;
547              const MatchChar *rstart = range + 1;
548              const MatchChar *rend = 0;
549              MatchChar compchar;
550            
551 kumpf 1.35   for (rend = rstart; *rend && *rend != ']'; rend++);
552 karl  1.36   if (*rend == ']') {  // if there is an end to this pattern
553 kumpf 1.35     for (compchar = *rstart; rstart != rend; rstart++) {
554 karl  1.36       if (_Equal(*rstart, c, nocase))
555 kumpf 1.35         return ++rend;
556                  if (*rstart == '-') {
557                    rstart++;
558                    if (c >= compchar && c <= *rstart)
559                      return ++rend;
560                  }
561                }
562              }
563 karl  1.36   return (const MatchChar *)0;
564 kumpf 1.35 }
565            
566            static int
567 karl  1.36 _StringMatch( 
568                const MatchChar *testString, 
569                const MatchChar *pattern,
570                int nocase ) 		/* Ignore case if this is true */
571            {
572              const MatchChar *pat = pattern;
573              const MatchChar *str = testString;
574 kumpf 1.35   unsigned int done = 0;
575              unsigned int res = 0;  // the result: 1 == match
576            
577              while (!done) { // main loop walks through pattern and test string
578                //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
579                if (!*pat) {                                         //end of pattern
580                  done = 1;                                          // we're done
581                  if (!*str)                                         //end of test, too?
582                    res = 1;                                         // then we matched
583                } else {                                             //Not end of pattern
584                  if (!*str) {                                       // but end of test
585                    done = 1;                                        // We're done
586                    if (*pat == '*')                                 // If pattern openends
587                      res = 1;                                       //  then we matched
588                  } else {                                           //Not end of test
589                    if (*pat == '*') {                               //Ambiguuity found
590                      if (!*++pat) {                                 //and it ends pattern
591                        done = 1;                                    //  then we're done
592                        res = 1;                                     //  and match
593                      } else {                                       //if it doesn't end
594                        while (!done) {                              //  until we're done
595 karl  1.36               if (_StringMatch(str, pat, nocase)) {      //  we recurse
596 kumpf 1.35                 done = 1;                                //if it recurses true
597                            res = 1;                                 //  we done and match
598                          } else {                                   //it recurses false
599                            if (!*str)                               // see if test is done
600                              done = 1;                              //  yes: we done
601                            else                                     // not done:
602                              str++;                                 //   keep testing
603                          } // end test on recursive call
604                        } // end looping on recursive calls
605                      } // end logic when pattern is ambiguous
606                    } else {                                         //pattern not ambiguus
607                      if (*pat == '?') {                             //pattern is 'any'
608                        pat++, str++;                                //  so move along
609                      } else if (*pat == '[') {                      //see if it's a range
610 karl  1.36             pat = _matchrange(pat, *str, nocase);         // and is a match
611 kumpf 1.35             if (!pat) {                                  //It is not a match
612                          done = 1;                                  //  we're done
613 kumpf 1.42               res = 0;                                   //  no match
614 kumpf 1.35             } else {                                     //Range matches
615                          str++, pat++;                              //  keep going
616                        }
617                      } else {               // only case left is individual characters
618 karl  1.36             if (!_Equal(*pat++, *str++, nocase))         // if they don't match
619 kumpf 1.35               done = 1;                                  //   bail.
620                      }
621                    }  // end ("pattern is not ambiguous (*)" logic
622                  } // end logic when pattern and string still have data
623                } // end logic when pattern still has data
624              } // end main loop
625              return res;
626            }
627            
628 kumpf 1.39 
629 karl  1.36 Boolean String::match(const String& str, const String& pattern)
630            {
631                return _StringMatch(
632            	(Uint16*)str.getData(), (Uint16*)pattern.getData(), 0) != 0;
633            }
634            
635            Boolean String::matchNoCase(const String& str, const String& pattern)
636            {
637                return _StringMatch(
638            	(Uint16*)str.getData(), (Uint16*)pattern.getData(), 1) != 0;
639 kumpf 1.39 }
640            
641            
642            ///////////////////////////////////////////////////////////////////////////////
643            //
644            // String-related functions
645            //
646            ///////////////////////////////////////////////////////////////////////////////
647            
648            Boolean operator==(const String& str1, const String& str2)
649            {
650                return String::equal(str1, str2);
651            }
652            
653            Boolean operator==(const String& str1, const char* str2)
654            {
655                return String::equal(str1, str2);
656            }
657            
658            Boolean operator==(const char* str1, const String& str2)
659            {
660 kumpf 1.39     return String::equal(str1, str2);
661            }
662            
663            Boolean operator!=(const String& str1, const String& str2)
664            {
665                return !String::equal(str1, str2);
666            }
667            
668 kumpf 1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
669 kumpf 1.39 {
670 kumpf 1.47     for (Uint32 i = 0, n = str.size(); i < n; i++)
671 kumpf 1.50     {
672                    Uint16 code = str[i];
673            
674                    if (code > 0 && code <= PEGASUS_MAX_PRINTABLE_CHAR)
675                    {
676                        os << char(code);
677                    }
678                    else
679                    {
680                        // Print in hex format:
681                        char buffer[8];
682                        sprintf(buffer, "\\x%04X", code);
683                        os << buffer;
684                    }
685                }
686 kumpf 1.39 
687                return os;
688            }
689            
690            String operator+(const String& str1, const String& str2)
691            {
692                return String(str1).append(str2);
693            }
694            
695            Boolean operator<(const String& str1, const String& str2)
696            {
697 kumpf 1.43     return String::compare(str1, str2) < 0;
698 kumpf 1.39 }
699            
700            Boolean operator<=(const String& str1, const String& str2)
701            {
702 kumpf 1.43     return String::compare(str1, str2) <= 0;
703 kumpf 1.39 }
704            
705            Boolean operator>(const String& str1, const String& str2)
706            {
707 kumpf 1.43     return String::compare(str1, str2) > 0;
708 kumpf 1.39 }
709            
710            Boolean operator>=(const String& str1, const String& str2)
711            {
712 kumpf 1.43     return String::compare(str1, str2) >= 0;
713 kumpf 1.39 }
714            
715            int CompareNoCase(const char* s1, const char* s2)
716            {
717                while (*s1 && *s2)
718                {
719            	int r = tolower(*s1++) - tolower(*s2++);
720            
721            	if (r)
722            	    return r;
723                }
724            
725                if (*s2)
726            	return -1;
727                else if (*s1)
728            	return 1;
729            
730                return 0;
731            }
732            
733            int EqualNoCase(const char* s1, const char* s2)
734 kumpf 1.39 {
735                return CompareNoCase(s1, s2) == 0;
736 karl  1.36 }
737 kumpf 1.35 
738 mike  1.27 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2