(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 String& String::operator+=(const String& str)
302 mike  1.27 {
303 kumpf 1.39     return append(str);
304 mike  1.27 }
305            
306 kumpf 1.39 String& String::operator+=(Char16 c)
307 mike  1.27 {
308 kumpf 1.39     return append(c);
309 mike  1.27 }
310            
311 kumpf 1.39 String& String::operator+=(char c)
312 mike  1.27 {
313 kumpf 1.39     return append(Char16(c));
314 mike  1.27 }
315            
316 kumpf 1.39 void String::remove(Uint32 pos, Uint32 size)
317 mike  1.27 {
318 kumpf 1.39     if (size == PEG_NOT_FOUND)
319            	size = this->size() - pos;
320 mike  1.27 
321 kumpf 1.39     if (pos + size > this->size())
322 kumpf 1.49 	throw IndexOutOfBoundsException();
323 mike  1.27 
324 kumpf 1.39     if (size)
325 kumpf 1.43 	_rep->c16a.remove(pos, size);
326 mike  1.27 }
327            
328            String String::subString(Uint32 pos, Uint32 length) const
329            {
330                if (pos < size())
331                {
332            	if (length == PEG_NOT_FOUND)
333            	    length = size() - pos;
334            
335            	return String(getData() + pos, length);
336                }
337                else
338            	return String();
339            }
340            
341            Uint32 String::find(Char16 c) const
342            {
343                const Char16* first = getData();
344            
345                for (const Char16* p = first; *p; p++)
346                {
347 mike  1.27 	if (*p == c)
348            	    return  p - first;
349                }
350            
351                return PEG_NOT_FOUND;
352            }
353            
354 mike  1.30 Uint32 String::find(Uint32 pos, Char16 c) const
355            {
356                const Char16* data = getData();
357            
358                for (Uint32 i = pos, n = size(); i < n; i++)
359                {
360            	if (data[i] == c)
361            	    return i;
362                }
363            
364                return PEG_NOT_FOUND;
365            }
366            
367 mike  1.27 Uint32 String::find(const String& s) const
368            {
369                const Char16* pSubStr = s.getData();
370                const Char16* pStr = getData();
371                Uint32 subStrLen = s.size();
372                Uint32 strLen = size();
373            
374 mike  1.30     if (subStrLen > strLen)
375                {
376                    return PEG_NOT_FOUND;
377                }
378            
379 mike  1.27     // loop to find first char match
380                Uint32 loc = 0;
381                for( ; loc <= (strLen-subStrLen); loc++)
382                {
383            	if (*pStr++ == *pSubStr)  // match first char
384            	{
385            	    // point to substr 2nd char
386            	    const Char16* p = pSubStr + 1;
387            
388            	    // Test remaining chars for equal
389            	    Uint32 i = 1;
390            	    for (; i < subStrLen; i++)
391            		if (*pStr++ != *p++ )
392            		    {pStr--; break;} // break from loop
393            	    if (i == subStrLen)
394            		return loc;
395            	}
396                }
397                return PEG_NOT_FOUND;
398            }
399            
400 mike  1.27 Uint32 String::reverseFind(Char16 c) const
401            {
402                const Char16* first = getData();
403                const Char16* last = getData() + size();
404            
405                while (last != first)
406                {
407            	if (*--last == c)
408            	    return last - first;
409                }
410            
411                return PEG_NOT_FOUND;
412            }
413            
414            void String::toLower()
415            {
416 kumpf 1.43     for (Char16* p = &_rep->c16a[0]; *p; p++)
417 mike  1.27     {
418 kumpf 1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
419 mike  1.27 	    *p = tolower(*p);
420                }
421 kumpf 1.39 }
422            
423 kumpf 1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
424 kumpf 1.39 {
425 kumpf 1.43     const Char16* s1c16 = s1.getData();
426                const Char16* s2c16 = s2.getData();
427 kumpf 1.39 
428                while (n--)
429 mike  1.27     {
430 kumpf 1.43 	int r = *s1c16++ - *s2c16++;
431 mike  1.27 
432            	if (r)
433            	    return r;
434                }
435            
436                return 0;
437            }
438            
439 kumpf 1.43 int String::compare(const String& s1, const String& s2)
440 mike  1.30 {
441 kumpf 1.43     const Char16* s1c16 = s1.getData();
442                const Char16* s2c16 = s2.getData();
443            
444                while (*s1c16 && *s2c16)
445 mike  1.30     {
446 kumpf 1.43 	int r = *s1c16++ - *s2c16++;
447 mike  1.30 
448            	if (r)
449            	    return r;
450                }
451            
452 kumpf 1.43     if (*s2c16)
453 mike  1.30 	return -1;
454 kumpf 1.43     else if (*s1c16)
455 mike  1.30 	return 1;
456            
457                return 0;
458            }
459            
460 kumpf 1.39 int String::compareNoCase(const char* s1, const char* s2, Uint32 n)
461 mike  1.27 {
462 kumpf 1.39     while (n--)
463 mike  1.27     {
464 kumpf 1.39 	int r = tolower(*s1++) - tolower(*s2++);
465 mike  1.27 
466 kumpf 1.39 	if (r)
467            	    return r;
468 mike  1.27     }
469            
470 kumpf 1.39     return 0;
471 mike  1.27 }
472            
473 kumpf 1.39 int String::compareNoCase(const char* s1, const char* s2)
474 mike  1.27 {
475                while (*s1 && *s2)
476                {
477            	int r = tolower(*s1++) - tolower(*s2++);
478            
479            	if (r)
480            	    return r;
481                }
482            
483                if (*s2)
484            	return -1;
485                else if (*s1)
486            	return 1;
487            
488                return 0;
489            }
490            
491 kumpf 1.40 int String::compareNoCase(const String& s1, const String& s2)
492            {
493                const Char16* _s1 = s1.getData();
494                const Char16* _s2 = s2.getData();
495            
496                while (*_s1 && *_s2)
497                {
498                    int r;
499            
500 kumpf 1.46         if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
501                        *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
502 kumpf 1.40         {
503                        r = tolower(*_s1++) - tolower(*_s2++);
504                    }
505                    else
506                    {
507                        r = *_s1++ - *_s2++;
508                    }
509            
510            	if (r)
511            	    return r;
512                }
513            
514                if (*_s2)
515            	return -1;
516                else if (*_s1)
517            	return 1;
518            
519                return 0;
520            }
521            
522 kumpf 1.39 Boolean String::equal(const String& str1, const String& str2)
523 mike  1.27 {
524 kumpf 1.43     return String::compare(str1, str2) == 0;
525 mike  1.27 }
526            
527 kumpf 1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
528 mike  1.27 {
529 kumpf 1.39     if (str1.size() != str2.size())
530            	return false;
531            
532                const Char16* p = str1.getData();
533                const Char16* q = str2.getData();
534            
535                Uint32 n = str1.size();
536 mike  1.27 
537 kumpf 1.39     while (n--)
538                {
539 kumpf 1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
540                        *q <= PEGASUS_MAX_PRINTABLE_CHAR)
541 kumpf 1.39 	{
542            	    if (tolower(*p++) != tolower(*q++))
543            		return false;
544            	}
545            	else if (*p++ != *q++)
546            	    return false;
547                }
548 mike  1.28 
549 kumpf 1.39     return true;
550 mike  1.27 }
551            
552 kumpf 1.42 
553            // ATTN-RK-P3-20020603: This code is not completely correct
554 karl  1.36  // Wildcard String matching function that may be useful in the future
555            // The following code was provided by Bob Blair.
556            
557            /* _StringMatch Match input MatchString against a GLOB style pattern
558                   Note that MatchChar is the char type so that this source
559                   in portable to different string types. This is an internal function
560             
561              Results: The return value is 1 if string matches pattern, and
562             	0 otherwise.  The matching operation permits the following
563             	special characters in the pattern: *?\[] (see the manual
564             	entry for details on what these mean).
565             
566              Side effects: None.
567             */
568            
569            /* MatchChar defined as a separate entity because this function source used
570                elsewhere was an unsigned char *. Here we use Uint16 to  maintain 16 bit 
571                size.
572            */
573            typedef Uint16 MatchChar;
574            
575 karl  1.36 inline Uint16 _ToLower(Uint16 ch)
576            {
577 kumpf 1.46     return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
578 karl  1.36 }
579            
580            inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
581            {
582                if (nocase)
583            	return _ToLower(ch1) == _ToLower(ch2);
584                else
585            	return ch1 == ch2;
586            }
587 mike  1.28 
588 kumpf 1.35 
589 karl  1.36 static const MatchChar *
590            _matchrange(const MatchChar *range, MatchChar c, int nocase)
591            {
592              const MatchChar *p = range;
593              const MatchChar *rstart = range + 1;
594              const MatchChar *rend = 0;
595              MatchChar compchar;
596            
597 kumpf 1.35   for (rend = rstart; *rend && *rend != ']'; rend++);
598 karl  1.36   if (*rend == ']') {  // if there is an end to this pattern
599 kumpf 1.35     for (compchar = *rstart; rstart != rend; rstart++) {
600 karl  1.36       if (_Equal(*rstart, c, nocase))
601 kumpf 1.35         return ++rend;
602                  if (*rstart == '-') {
603                    rstart++;
604                    if (c >= compchar && c <= *rstart)
605                      return ++rend;
606                  }
607                }
608              }
609 karl  1.36   return (const MatchChar *)0;
610 kumpf 1.35 }
611            
612            static int
613 karl  1.36 _StringMatch( 
614                const MatchChar *testString, 
615                const MatchChar *pattern,
616                int nocase ) 		/* Ignore case if this is true */
617            {
618              const MatchChar *pat = pattern;
619              const MatchChar *str = testString;
620 kumpf 1.35   unsigned int done = 0;
621              unsigned int res = 0;  // the result: 1 == match
622            
623              while (!done) { // main loop walks through pattern and test string
624                //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
625                if (!*pat) {                                         //end of pattern
626                  done = 1;                                          // we're done
627                  if (!*str)                                         //end of test, too?
628                    res = 1;                                         // then we matched
629                } else {                                             //Not end of pattern
630                  if (!*str) {                                       // but end of test
631                    done = 1;                                        // We're done
632                    if (*pat == '*')                                 // If pattern openends
633                      res = 1;                                       //  then we matched
634                  } else {                                           //Not end of test
635                    if (*pat == '*') {                               //Ambiguuity found
636                      if (!*++pat) {                                 //and it ends pattern
637                        done = 1;                                    //  then we're done
638                        res = 1;                                     //  and match
639                      } else {                                       //if it doesn't end
640                        while (!done) {                              //  until we're done
641 karl  1.36               if (_StringMatch(str, pat, nocase)) {      //  we recurse
642 kumpf 1.35                 done = 1;                                //if it recurses true
643                            res = 1;                                 //  we done and match
644                          } else {                                   //it recurses false
645                            if (!*str)                               // see if test is done
646                              done = 1;                              //  yes: we done
647                            else                                     // not done:
648                              str++;                                 //   keep testing
649                          } // end test on recursive call
650                        } // end looping on recursive calls
651                      } // end logic when pattern is ambiguous
652                    } else {                                         //pattern not ambiguus
653                      if (*pat == '?') {                             //pattern is 'any'
654                        pat++, str++;                                //  so move along
655                      } else if (*pat == '[') {                      //see if it's a range
656 karl  1.36             pat = _matchrange(pat, *str, nocase);         // and is a match
657 kumpf 1.35             if (!pat) {                                  //It is not a match
658                          done = 1;                                  //  we're done
659 kumpf 1.42               res = 0;                                   //  no match
660 kumpf 1.35             } else {                                     //Range matches
661                          str++, pat++;                              //  keep going
662                        }
663                      } else {               // only case left is individual characters
664 karl  1.36             if (!_Equal(*pat++, *str++, nocase))         // if they don't match
665 kumpf 1.35               done = 1;                                  //   bail.
666                      }
667                    }  // end ("pattern is not ambiguous (*)" logic
668                  } // end logic when pattern and string still have data
669                } // end logic when pattern still has data
670              } // end main loop
671              return res;
672            }
673            
674 kumpf 1.39 
675 karl  1.36 Boolean String::match(const String& str, const String& pattern)
676            {
677                return _StringMatch(
678            	(Uint16*)str.getData(), (Uint16*)pattern.getData(), 0) != 0;
679            }
680            
681            Boolean String::matchNoCase(const String& str, const String& pattern)
682            {
683                return _StringMatch(
684            	(Uint16*)str.getData(), (Uint16*)pattern.getData(), 1) != 0;
685 kumpf 1.39 }
686            
687            
688            ///////////////////////////////////////////////////////////////////////////////
689            //
690            // String-related functions
691            //
692            ///////////////////////////////////////////////////////////////////////////////
693            
694            Boolean operator==(const String& str1, const String& str2)
695            {
696                return String::equal(str1, str2);
697            }
698            
699            Boolean operator==(const String& str1, const char* str2)
700            {
701                return String::equal(str1, str2);
702            }
703            
704            Boolean operator==(const char* str1, const String& str2)
705            {
706 kumpf 1.39     return String::equal(str1, str2);
707            }
708            
709            Boolean operator!=(const String& str1, const String& str2)
710            {
711                return !String::equal(str1, str2);
712            }
713            
714 kumpf 1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
715 kumpf 1.39 {
716 kumpf 1.47     for (Uint32 i = 0, n = str.size(); i < n; i++)
717            	os << str[i];
718 kumpf 1.39 
719                return os;
720            }
721            
722            String operator+(const String& str1, const String& str2)
723            {
724                return String(str1).append(str2);
725            }
726            
727            Boolean operator<(const String& str1, const String& str2)
728            {
729 kumpf 1.43     return String::compare(str1, str2) < 0;
730 kumpf 1.39 }
731            
732            Boolean operator<=(const String& str1, const String& str2)
733            {
734 kumpf 1.43     return String::compare(str1, str2) <= 0;
735 kumpf 1.39 }
736            
737            Boolean operator>(const String& str1, const String& str2)
738            {
739 kumpf 1.43     return String::compare(str1, str2) > 0;
740 kumpf 1.39 }
741            
742            Boolean operator>=(const String& str1, const String& str2)
743            {
744 kumpf 1.43     return String::compare(str1, str2) >= 0;
745 kumpf 1.39 }
746            
747            int CompareNoCase(const char* s1, const char* s2)
748            {
749                while (*s1 && *s2)
750                {
751            	int r = tolower(*s1++) - tolower(*s2++);
752            
753            	if (r)
754            	    return r;
755                }
756            
757                if (*s2)
758            	return -1;
759                else if (*s1)
760            	return 1;
761            
762                return 0;
763            }
764            
765            int EqualNoCase(const char* s1, const char* s2)
766 kumpf 1.39 {
767                return CompareNoCase(s1, s2) == 0;
768 karl  1.36 }
769 kumpf 1.35 
770 mike  1.27 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2