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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2