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

  1 karl  1.98 //%2005////////////////////////////////////////////////////////////////////////
  2 mike  1.27 //
  3 karl  1.97 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.85 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.97 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.98 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 mike  1.27 //
 12            // Permission is hereby granted, free of charge, to any person obtaining a copy
 13 kumpf 1.41 // of this software and associated documentation files (the "Software"), to
 14            // deal in the Software without restriction, including without limitation the
 15            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 16 mike  1.27 // sell copies of the Software, and to permit persons to whom the Software is
 17            // furnished to do so, subject to the following conditions:
 18            // 
 19 kumpf 1.41 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 20 mike  1.27 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 21            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 22 kumpf 1.41 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 23            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 24            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 25 mike  1.27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 26            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27            //
 28            //==============================================================================
 29            //
 30            // Author: Mike Brasher (mbrasher@bmc.com)
 31            //
 32 kumpf 1.39 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 33 mike  1.27 //
 34            //%/////////////////////////////////////////////////////////////////////////////
 35            
 36            
 37            #include <cctype>
 38 kumpf 1.64 #include <cstring>
 39 mike  1.27 #include "String.h"
 40 kumpf 1.43 #include "Array.h"
 41 kumpf 1.48 #include "InternalException.h"
 42 mike  1.27 #include <iostream>
 43 kumpf 1.63 #include <fstream>
 44 mike  1.27 
 45 david 1.69 #include "CommonUTF.h"
 46            
 47            #ifdef PEGASUS_HAS_ICU
 48 chuck 1.74 #include <unicode/unistr.h>
 49 david 1.69 #endif
 50            
 51 mike  1.28 PEGASUS_USING_STD;
 52            
 53 mike  1.27 PEGASUS_NAMESPACE_BEGIN
 54            
 55 kumpf 1.39 ///////////////////////////////////////////////////////////////////////////////
 56            //
 57 kumpf 1.54 // CString
 58            //
 59            ///////////////////////////////////////////////////////////////////////////////
 60            
 61            CString::CString()
 62                : _rep(0)
 63            {
 64            }
 65            
 66            CString::CString(const CString& cstr)
 67            {
 68 kumpf 1.82     _rep = 0;
 69            
 70                if (cstr._rep)
 71                {
 72                    _rep = (void*)new char[strlen((char*)cstr._rep)+1];
 73                    strcpy((char*)_rep, (char*)cstr._rep);
 74                }
 75 kumpf 1.54 }
 76            
 77            CString::CString(char* cstr)
 78                : _rep(cstr)
 79            {
 80            }
 81            
 82            CString::~CString()
 83            {
 84                if (_rep)
 85 kumpf 1.82     {
 86 kumpf 1.59         delete [] (char*)_rep;
 87 kumpf 1.82     }
 88 kumpf 1.54 }
 89            
 90 kumpf 1.56 CString& CString::operator=(const CString& cstr)
 91            {
 92 kumpf 1.82     if (&cstr != this)
 93 kumpf 1.81     {
 94 kumpf 1.82         if (_rep)
 95                    {
 96                        delete [] (char*)_rep;
 97                        _rep = 0;
 98                    }
 99                    if (cstr._rep)
100                    {
101                        _rep = (char*)new char[strlen((char*)cstr._rep)+1];
102                        strcpy((char*)_rep, (char*)cstr._rep);
103                    }
104 kumpf 1.81     }
105 kumpf 1.56     return *this;
106            }
107            
108 kumpf 1.54 CString::operator const char*() const
109            {
110 kumpf 1.59     return (char*)_rep;
111 kumpf 1.54 }
112            
113            ///////////////////////////////////////////////////////////////////////////////
114            //
115 kumpf 1.39 // String
116            //
117            ///////////////////////////////////////////////////////////////////////////////
118            
119 kumpf 1.37 const String String::EMPTY = String();
120 mike  1.27 
121 kumpf 1.38 Uint32 _strnlen(const char* str, Uint32 n)
122            {
123                if (!str)
124            	throw NullPointer();
125            
126                for (Uint32 i=0; i<n; i++)
127                {
128                    if (!*str)
129                    {
130                        return i;
131                    }
132                }
133            
134                return n;
135            }
136            
137            Uint32 _strnlen(const Char16* str, Uint32 n)
138            {
139                if (!str)
140            	throw NullPointer();
141            
142 kumpf 1.38     for (Uint32 i=0; i<n; i++)
143                {
144                    if (!*str)
145                    {
146                        return i;
147                    }
148                }
149            
150                return n;
151            }
152            
153 kumpf 1.39 inline Uint32 _StrLen(const char* str)
154 mike  1.27 {
155                if (!str)
156            	throw NullPointer();
157            
158                return strlen(str);
159            }
160            
161 kumpf 1.39 inline Uint32 _StrLen(const Char16* str)
162 mike  1.27 {
163                if (!str)
164            	throw NullPointer();
165            
166                Uint32 n = 0;
167            
168                while (*str++)
169            	n++;
170            
171                return n;
172            }
173            
174 kumpf 1.43 class StringRep
175            {
176            public:
177                StringRep()
178                {}
179                StringRep(const StringRep& r)
180                    : c16a(r.c16a)
181                {}
182                StringRep(const Char16* str)
183                    : c16a(str, _StrLen(str) + 1)
184                {}
185            
186                Array<Char16> c16a;
187            };
188            
189 mike  1.27 String::String()
190            {
191 kumpf 1.43     _rep = new StringRep;
192                _rep->c16a.append('\0');
193 mike  1.27 }
194            
195 kumpf 1.39 String::String(const String& str)
196 mike  1.27 {
197 tony  1.66   if (str._rep != NULL)
198              {
199 kumpf 1.43     _rep = new StringRep(*str._rep);
200 tony  1.66   }
201              else
202              {
203                _rep = new StringRep();
204              }
205 kumpf 1.39 }
206 tony  1.66 
207 mike  1.27 
208 kumpf 1.39 String::String(const String& str, Uint32 n)
209            {
210 kumpf 1.43     _rep = new StringRep;
211 kumpf 1.55     assign(str.getChar16Data(), n);
212 kumpf 1.39 }
213            
214            String::String(const Char16* str)
215            {
216 kumpf 1.43     _rep = new StringRep(str);
217 mike  1.27 }
218            
219 kumpf 1.39 String::String(const Char16* str, Uint32 n)
220            {
221 kumpf 1.43     _rep = new StringRep;
222 kumpf 1.39     assign(str, n);
223            }
224            
225            String::String(const char* str)
226 mike  1.27 {
227 kumpf 1.43     _rep = new StringRep;
228 kumpf 1.39     assign(str);
229 mike  1.27 }
230            
231 kumpf 1.39 String::String(const char* str, Uint32 n)
232 mike  1.27 {
233 kumpf 1.43     _rep = new StringRep;
234 kumpf 1.39     assign(str, n);
235            }
236 mike  1.27 
237 kumpf 1.39 String::~String()
238            {
239 kumpf 1.43     delete _rep;
240 mike  1.27 }
241            
242 kumpf 1.39 String& String::operator=(const String& str)
243 mike  1.27 {
244 kumpf 1.82     if (&str != this)
245                {
246                    assign(str);
247                }
248                return *this;
249 mike  1.27 }
250            
251 kumpf 1.39 String& String::assign(const String& str)
252 mike  1.27 {
253 kumpf 1.43     _rep->c16a = str._rep->c16a;
254 kumpf 1.39     return *this;
255 mike  1.27 }
256            
257 kumpf 1.39 String& String::assign(const Char16* str)
258 mike  1.27 {
259 kumpf 1.43     _rep->c16a.clear();
260                _rep->c16a.append(str, _StrLen(str) + 1);
261 mike  1.27     return *this;
262            }
263            
264            String& String::assign(const Char16* str, Uint32 n)
265            {
266 kumpf 1.43     _rep->c16a.clear();
267 kumpf 1.38     Uint32 m = _strnlen(str, n);
268 kumpf 1.43     _rep->c16a.append(str, m);
269                _rep->c16a.append('\0');
270 mike  1.27     return *this;
271            }
272            
273 kumpf 1.39 String& String::assign(const char* str, Uint32 n)
274 mike  1.27 {
275 david 1.90     char *tmpStr = new char[n+1];
276                memset(tmpStr,0x00,n+1);
277 mike  1.27 
278 david 1.90     strncpy(tmpStr,str,n);
279                assign(tmpStr);
280 kumpf 1.96     delete [] tmpStr;
281 mike  1.27 
282                return *this;
283            }
284            
285 kumpf 1.39 void String::clear()
286            {
287 kumpf 1.43     _rep->c16a.clear();
288                _rep->c16a.append('\0');
289 kumpf 1.39 }
290            
291 kumpf 1.43 void String::reserveCapacity(Uint32 capacity)
292 kumpf 1.39 {
293 kumpf 1.45     _rep->c16a.reserveCapacity(capacity + 1);
294 kumpf 1.39 }
295            
296            Uint32 String::size() const
297            {
298 kumpf 1.43     return _rep->c16a.size() - 1;
299 kumpf 1.39 }
300            
301 kumpf 1.55 const Char16* String::getChar16Data() const
302 kumpf 1.39 {
303 kumpf 1.43     return _rep->c16a.getData();
304 kumpf 1.39 }
305            
306 kumpf 1.53 Char16& String::operator[](Uint32 index)
307 mike  1.27 {
308 kumpf 1.53     if (index > size())
309 kumpf 1.49 	throw IndexOutOfBoundsException();
310 mike  1.27 
311 kumpf 1.53     return _rep->c16a[index];
312 mike  1.27 }
313            
314 kumpf 1.53 const Char16 String::operator[](Uint32 index) const
315 mike  1.27 {
316 kumpf 1.53     if (index > size())
317 kumpf 1.49 	throw IndexOutOfBoundsException();
318 mike  1.27 
319 kumpf 1.53     return _rep->c16a[index];
320 mike  1.27 }
321            
322 kumpf 1.39 String& String::append(const Char16& c)
323            {
324 kumpf 1.43     _rep->c16a.insert(_rep->c16a.size() - 1, c);
325 kumpf 1.39     return *this;
326            }
327            
328 mike  1.27 String& String::append(const Char16* str, Uint32 n)
329            {
330 kumpf 1.38     Uint32 m = _strnlen(str, n);
331 kumpf 1.45     _rep->c16a.reserveCapacity(_rep->c16a.size() + m);
332 kumpf 1.43     _rep->c16a.remove(_rep->c16a.size() - 1);
333                _rep->c16a.append(str, m);
334                _rep->c16a.append('\0');
335 mike  1.27     return *this;
336            }
337            
338 kumpf 1.39 String& String::append(const String& str)
339 mike  1.27 {
340 kumpf 1.55     return append(str.getChar16Data(), str.size());
341 mike  1.27 }
342            
343 kumpf 1.53 void String::remove(Uint32 index, Uint32 size)
344 mike  1.27 {
345 kumpf 1.39     if (size == PEG_NOT_FOUND)
346 kumpf 1.53 	size = this->size() - index;
347 mike  1.27 
348 kumpf 1.53     if (index + size > this->size())
349 kumpf 1.49 	throw IndexOutOfBoundsException();
350 mike  1.27 
351 kumpf 1.39     if (size)
352 kumpf 1.53 	_rep->c16a.remove(index, size);
353 mike  1.27 }
354            
355 kumpf 1.53 String String::subString(Uint32 index, Uint32 length) const
356 mike  1.27 {
357 kumpf 1.53     if (index < size())
358 mike  1.27     {
359 kumpf 1.57 	if ((length == PEG_NOT_FOUND) || (length > size() - index))
360 kumpf 1.53 	    length = size() - index;
361 mike  1.27 
362 kumpf 1.55 	return String(getChar16Data() + index, length);
363 mike  1.27     }
364                else
365            	return String();
366            }
367            
368            Uint32 String::find(Char16 c) const
369            {
370 kumpf 1.55     const Char16* first = getChar16Data();
371 mike  1.27 
372                for (const Char16* p = first; *p; p++)
373                {
374            	if (*p == c)
375            	    return  p - first;
376                }
377            
378                return PEG_NOT_FOUND;
379            }
380            
381 kumpf 1.53 Uint32 String::find(Uint32 index, Char16 c) const
382 mike  1.30 {
383 kumpf 1.55     const Char16* data = getChar16Data();
384 mike  1.30 
385 kumpf 1.53     for (Uint32 i = index, n = size(); i < n; i++)
386 mike  1.30     {
387            	if (data[i] == c)
388            	    return i;
389                }
390            
391                return PEG_NOT_FOUND;
392            }
393            
394 mike  1.27 Uint32 String::find(const String& s) const
395            {
396 kumpf 1.55     const Char16* pSubStr = s.getChar16Data();
397                const Char16* pStr = getChar16Data();
398 mike  1.27     Uint32 subStrLen = s.size();
399                Uint32 strLen = size();
400            
401 mike  1.30     if (subStrLen > strLen)
402                {
403                    return PEG_NOT_FOUND;
404                }
405            
406 mike  1.27     // loop to find first char match
407                Uint32 loc = 0;
408                for( ; loc <= (strLen-subStrLen); loc++)
409                {
410            	if (*pStr++ == *pSubStr)  // match first char
411            	{
412            	    // point to substr 2nd char
413            	    const Char16* p = pSubStr + 1;
414            
415            	    // Test remaining chars for equal
416            	    Uint32 i = 1;
417            	    for (; i < subStrLen; i++)
418            		if (*pStr++ != *p++ )
419 humberto 1.88 		    {pStr-=i; break;} // break from loop
420 mike     1.27 	    if (i == subStrLen)
421               		return loc;
422               	}
423                   }
424                   return PEG_NOT_FOUND;
425               }
426               
427               Uint32 String::reverseFind(Char16 c) const
428               {
429 kumpf    1.55     const Char16* first = getChar16Data();
430                   const Char16* last = getChar16Data() + size();
431 mike     1.27 
432                   while (last != first)
433                   {
434               	if (*--last == c)
435               	    return last - first;
436                   }
437               
438                   return PEG_NOT_FOUND;
439               }
440               
441               void String::toLower()
442               {
443 david    1.90     const char * noLocale = NULL;
444                   String::toLower(noLocale);
445               }
446               void String::toLower(const char * strLocale)
447               {
448 david    1.69 #ifdef PEGASUS_HAS_ICU
449 chuck    1.78     UnicodeString UniStr((const UChar *)_rep->c16a.getData());
450 david    1.90     if(strLocale == NULL)
451                   {
452                      	UniStr.toLower();
453                   }
454                   else
455                   {
456               	Locale loc(strLocale);
457               	if(loc.isBogus())
458               	{
459               	    throw InvalidNameException(String(strLocale));
460               	}
461               	UniStr.toLower(loc);
462                   }
463 david    1.80     UniStr.append((UChar)'\0');   
464                   
465                   assign((Char16*)UniStr.getBuffer());
466 david    1.69 #else
467 kumpf    1.43     for (Char16* p = &_rep->c16a[0]; *p; p++)
468 mike     1.27     {
469 kumpf    1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
470 mike     1.27 	    *p = tolower(*p);
471                   }
472 david    1.69 #endif
473 kumpf    1.39 }
474               
475 david    1.90 void String::toUpper(const char * strLocale)
476               {
477               #ifdef PEGASUS_HAS_ICU
478                   UnicodeString UniStr((const UChar *)_rep->c16a.getData());
479                   if(strLocale == NULL)
480                   {
481                      	UniStr.toUpper();
482                   }
483                   else
484                   {
485               	Locale loc(strLocale);
486               	if(loc.isBogus())
487               	{
488               	    throw InvalidNameException(String(strLocale));
489               	}
490               	UniStr.toUpper(loc);
491                   }
492                   UniStr.append((UChar)'\0');   
493               
494                   assign((Char16*)UniStr.getBuffer());
495 david    1.91 #else
496                   for (Char16* p = &_rep->c16a[0]; *p; p++)
497                   {
498               	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
499               	    *p = toupper(*p);
500                   }
501 david    1.90 #endif
502               }
503               
504 kumpf    1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
505 kumpf    1.39 {
506 kumpf    1.55     const Char16* s1c16 = s1.getChar16Data();
507                   const Char16* s2c16 = s2.getChar16Data();
508 kumpf    1.39 
509                   while (n--)
510 mike     1.27     {
511 kumpf    1.43 	int r = *s1c16++ - *s2c16++;
512 mike     1.27 
513               	if (r)
514               	    return r;
515                   }
516               
517                   return 0;
518               }
519               
520 kumpf    1.43 int String::compare(const String& s1, const String& s2)
521 mike     1.30 {
522 kumpf    1.55     const Char16* s1c16 = s1.getChar16Data();
523                   const Char16* s2c16 = s2.getChar16Data();
524 kumpf    1.43 
525                   while (*s1c16 && *s2c16)
526 mike     1.30     {
527 kumpf    1.43 	int r = *s1c16++ - *s2c16++;
528 mike     1.30 
529               	if (r)
530               	    return r;
531                   }
532               
533 kumpf    1.43     if (*s2c16)
534 mike     1.30 	return -1;
535 kumpf    1.43     else if (*s1c16)
536 mike     1.30 	return 1;
537               
538                   return 0;
539               }
540               
541 kumpf    1.40 int String::compareNoCase(const String& s1, const String& s2)
542               {
543 david    1.90     const char * noLocale = NULL;
544                   return String::compareNoCase(s1, s2, noLocale);
545               }
546               
547               int String::compareNoCase(const String& s1, const String& s2,const char * strLocale)
548               {
549 david    1.69 #ifdef PEGASUS_HAS_ICU
550                   UnicodeString UniStr1((const UChar *)s1.getChar16Data(), (int32_t)s1.size());
551                   UnicodeString UniStr2((const UChar *)s2.getChar16Data(), (int32_t)s2.size());
552 david    1.90     if(strLocale == NULL)
553                   {
554                   	UniStr1.toLower();
555                   	UniStr2.toLower();
556                   }
557                   else
558                   {
559               	Locale loc(strLocale);
560               	if(loc.isBogus())
561               	{
562               	    throw InvalidNameException(String(strLocale));
563               	}
564                   	UniStr1.toLower(loc);
565                   	UniStr2.toLower(loc);
566                   }
567 chuck    1.89     // Note:  the ICU 2.6.1 documentation for UnicodeString::compare( ) is
568                   // backwards!  The API actually returns +1 if this is greater than text.
569                   // This is why the line below appears wrong based on the 2.6.1 docs.
570                   // (ref. bugzilla 1207)
571                   return (UniStr1.compare(UniStr2));
572 david    1.69 #else
573 kumpf    1.55     const Char16* _s1 = s1.getChar16Data();
574                   const Char16* _s2 = s2.getChar16Data();
575 kumpf    1.40 
576                   while (*_s1 && *_s2)
577                   {
578                       int r;
579               
580 kumpf    1.46         if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
581                           *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
582 kumpf    1.40         {
583                           r = tolower(*_s1++) - tolower(*_s2++);
584                       }
585                       else
586                       {
587                           r = *_s1++ - *_s2++;
588                       }
589               
590               	if (r)
591               	    return r;
592                   }
593               
594                   if (*_s2)
595               	return -1;
596                   else if (*_s1)
597               	return 1;
598               
599                   return 0;
600 david    1.69 #endif
601 kumpf    1.40 }
602               
603 kumpf    1.39 Boolean String::equal(const String& str1, const String& str2)
604 mike     1.27 {
605 kumpf    1.43     return String::compare(str1, str2) == 0;
606 mike     1.27 }
607               
608 kumpf    1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
609 mike     1.27 {
610 david    1.90     const char * noLocale = NULL;
611                   return String::equalNoCase(str1, str2, noLocale);
612               }
613               
614               Boolean String::equalNoCase(const String& str1, const String& str2,const char * strLocale)
615               {
616 david    1.69 #ifdef PEGASUS_HAS_ICU
617                   UnicodeString UniStr1((const UChar *)str1.getChar16Data(), (int32_t)str1.size());
618                   UnicodeString UniStr2((const UChar *)str2.getChar16Data(), (int32_t)str2.size());
619 david    1.90     if(strLocale == NULL)
620                   {
621                   	UniStr1.toLower();
622                   	UniStr2.toLower();
623                   }
624                   else
625                   {
626               	Locale loc(strLocale);
627               	if(loc.isBogus())
628               	{
629               	    throw InvalidNameException(String(strLocale));
630               	}
631                   	UniStr1.toLower(loc);
632                   	UniStr2.toLower(loc);
633                   }
634 david    1.69     return (UniStr1 == UniStr2);    
635               #else
636 kumpf    1.39     if (str1.size() != str2.size())
637               	return false;
638               
639 kumpf    1.55     const Char16* p = str1.getChar16Data();
640                   const Char16* q = str2.getChar16Data();
641 kumpf    1.39 
642                   Uint32 n = str1.size();
643 mike     1.27 
644 kumpf    1.39     while (n--)
645                   {
646 kumpf    1.46 	if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
647                           *q <= PEGASUS_MAX_PRINTABLE_CHAR)
648 kumpf    1.39 	{
649               	    if (tolower(*p++) != tolower(*q++))
650               		return false;
651               	}
652               	else if (*p++ != *q++)
653               	    return false;
654                   }
655 mike     1.28 
656 kumpf    1.39     return true;
657 david    1.69 #endif
658               }
659               
660               // UTF8 specific code:
661 david    1.90 String& String::assign(const char* str)
662               {
663                   _rep->c16a.clear();
664                   Uint32 n = strlen(str) + 1;
665               
666                   const Uint8 *strsrc = (Uint8 *)str;
667                   Uint8 *endsrc = (Uint8 *)&str[n-1];
668               
669                   Char16 *msg16 = new Char16[n];
670                   Uint16 *strtgt = (Uint16 *)msg16;
671                   Uint16 *endtgt = (Uint16 *)&msg16[n];
672               
673                   UTF8toUTF16(&strsrc,
674               		endsrc,
675               		&strtgt,
676               		endtgt);
677               
678                   Uint32 count;
679               
680                   for(count = 0; ((msg16[count]) != Char16(0x00)) && (count < (n - 1)); ++count);
681               
682 david    1.90     _rep->c16a.append(msg16, count);
683               
684                   _rep->c16a.append('\0');
685               
686                   delete [] msg16;
687               
688                   return *this;
689               }
690 mike     1.27 
691 david    1.90 CString String::getCString() const
692 david    1.69 {
693 david    1.79     Uint32 n = 3*size() + 1;
694 david    1.69     char* str = new char[n];
695               
696                   const Char16* msg16 = getChar16Data();
697               
698                   const Uint16 *strsrc = (Uint16 *)msg16;
699 david    1.71     Uint16 *endsrc = (Uint16 *)&msg16[size()+1];
700 david    1.69 
701                   Uint8 *strtgt = (Uint8 *)str;
702                   Uint8 *endtgt = (Uint8 *)&str[n];
703               
704                   UTF16toUTF8 (&strsrc,
705               		 endsrc,
706               		 &strtgt,
707               		 endtgt);
708               
709 david    1.71 	char* str1 = new char[strlen(str)+1];
710               	strcpy(str1,str);
711 david    1.72 	delete [] str;
712 david    1.71 
713                   return CString(str1);
714 david    1.69 }
715 kumpf    1.42 
716 kumpf    1.65 #if 0
717 kumpf    1.42 // ATTN-RK-P3-20020603: This code is not completely correct
718 karl     1.36  // Wildcard String matching function that may be useful in the future
719               // The following code was provided by Bob Blair.
720               
721               /* _StringMatch Match input MatchString against a GLOB style pattern
722                      Note that MatchChar is the char type so that this source
723                      in portable to different string types. This is an internal function
724                
725                 Results: The return value is 1 if string matches pattern, and
726                	0 otherwise.  The matching operation permits the following
727                	special characters in the pattern: *?\[] (see the manual
728                	entry for details on what these mean).
729 chuck    1.78 
730 karl     1.36  
731                 Side effects: None.
732                */
733 chuck    1.78   
734 karl     1.36 /* MatchChar defined as a separate entity because this function source used
735                   elsewhere was an unsigned char *. Here we use Uint16 to  maintain 16 bit 
736                   size.
737               */
738               typedef Uint16 MatchChar;
739               
740               inline Uint16 _ToLower(Uint16 ch)
741               {
742 david    1.69     // ICU_TODO:  If ICU is available we should do this the correct way.
743 kumpf    1.46     return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
744 karl     1.36 }
745               
746               inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
747               {
748 david    1.69     // ICU_TODO:  If ICU is available we should do this the correct way.
749 karl     1.36     if (nocase)
750               	return _ToLower(ch1) == _ToLower(ch2);
751                   else
752               	return ch1 == ch2;
753               }
754 mike     1.28 
755 kumpf    1.35 
756 karl     1.36 static const MatchChar *
757               _matchrange(const MatchChar *range, MatchChar c, int nocase)
758               {
759                 const MatchChar *p = range;
760                 const MatchChar *rstart = range + 1;
761                 const MatchChar *rend = 0;
762                 MatchChar compchar;
763               
764 kumpf    1.35   for (rend = rstart; *rend && *rend != ']'; rend++);
765 karl     1.36   if (*rend == ']') {  // if there is an end to this pattern
766 kumpf    1.35     for (compchar = *rstart; rstart != rend; rstart++) {
767 karl     1.36       if (_Equal(*rstart, c, nocase))
768 kumpf    1.35         return ++rend;
769                     if (*rstart == '-') {
770                       rstart++;
771                       if (c >= compchar && c <= *rstart)
772                         return ++rend;
773                     }
774                   }
775                 }
776 karl     1.36   return (const MatchChar *)0;
777 kumpf    1.35 }
778               
779               static int
780 karl     1.36 _StringMatch( 
781                   const MatchChar *testString, 
782                   const MatchChar *pattern,
783                   int nocase ) 		/* Ignore case if this is true */
784               {
785                 const MatchChar *pat = pattern;
786                 const MatchChar *str = testString;
787 kumpf    1.35   unsigned int done = 0;
788                 unsigned int res = 0;  // the result: 1 == match
789               
790                 while (!done) { // main loop walks through pattern and test string
791                   //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
792                   if (!*pat) {                                         //end of pattern
793                     done = 1;                                          // we're done
794                     if (!*str)                                         //end of test, too?
795                       res = 1;                                         // then we matched
796                   } else {                                             //Not end of pattern
797                     if (!*str) {                                       // but end of test
798                       done = 1;                                        // We're done
799                       if (*pat == '*')                                 // If pattern openends
800                         res = 1;                                       //  then we matched
801                     } else {                                           //Not end of test
802                       if (*pat == '*') {                               //Ambiguuity found
803                         if (!*++pat) {                                 //and it ends pattern
804                           done = 1;                                    //  then we're done
805                           res = 1;                                     //  and match
806                         } else {                                       //if it doesn't end
807                           while (!done) {                              //  until we're done
808 karl     1.36               if (_StringMatch(str, pat, nocase)) {      //  we recurse
809 kumpf    1.35                 done = 1;                                //if it recurses true
810                               res = 1;                                 //  we done and match
811                             } else {                                   //it recurses false
812                               if (!*str)                               // see if test is done
813                                 done = 1;                              //  yes: we done
814                               else                                     // not done:
815                                 str++;                                 //   keep testing
816                             } // end test on recursive call
817                           } // end looping on recursive calls
818                         } // end logic when pattern is ambiguous
819                       } else {                                         //pattern not ambiguus
820                         if (*pat == '?') {                             //pattern is 'any'
821                           pat++, str++;                                //  so move along
822                         } else if (*pat == '[') {                      //see if it's a range
823 karl     1.36             pat = _matchrange(pat, *str, nocase);         // and is a match
824 kumpf    1.35             if (!pat) {                                  //It is not a match
825                             done = 1;                                  //  we're done
826 kumpf    1.42               res = 0;                                   //  no match
827 kumpf    1.35             } else {                                     //Range matches
828                             str++, pat++;                              //  keep going
829                           }
830                         } else {               // only case left is individual characters
831 karl     1.36             if (!_Equal(*pat++, *str++, nocase))         // if they don't match
832 kumpf    1.35               done = 1;                                  //   bail.
833                         }
834                       }  // end ("pattern is not ambiguous (*)" logic
835                     } // end logic when pattern and string still have data
836                   } // end logic when pattern still has data
837                 } // end main loop
838                 return res;
839               }
840               
841 kumpf    1.39 
842 kumpf    1.65     /** match matches a string against a GLOB style pattern.
843                       Return trues if the String parameter matches the pattern. C-Shell style
844               	glob matching is used.
845                       @param str String to be matched against the pattern
846                       @param pattern Pattern to use in the match
847                       @return Boolean true if str matches pattern
848                       The pattern definition is as follows:
849                       <pre>
850                       *             Matches any number of any characters
851                       ?             Match exactly one character
852                       [chars]       Match any character in chars
853                       [chara-charb] Match any character in the range between chara and charb
854                       </pre>
855                       The literal characters *, ?, [, ] can be included in a string by
856                       escaping them with backslash "\".  Ranges of characters can be concatenated.
857                       <pre>
858                       examples:
859                       Boolean result = String::match("This is a test", "*is*");
860                       Boolean works =  String::match("abcdef123", "*[0-9]");
861                       </pre>
862                   */
863 karl     1.36 Boolean String::match(const String& str, const String& pattern)
864               {
865                   return _StringMatch(
866 kumpf    1.55 	(Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 0) != 0;
867 karl     1.36 }
868               
869 kumpf    1.65     /** matchNoCase Matches a String against a GLOB style pattern independent
870                       of case. 
871                       Returns true if the str parameter matches the pattern. C-Shell style
872               	glob matching is used. Ignore case in all comparisons. Case is
873                       ignored in the match.
874                       @parm str String containing the string to be matched\
875                       @parm pattern GLOB style patterh to use in the match.
876                       @return Boolean true if str matches patterh
877                       @SeeAlso match
878                   */
879 karl     1.36 Boolean String::matchNoCase(const String& str, const String& pattern)
880               {
881                   return _StringMatch(
882 kumpf    1.55 	(Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 1) != 0;
883 kumpf    1.39 }
884 kumpf    1.65 #endif
885 kumpf    1.39 
886               
887               ///////////////////////////////////////////////////////////////////////////////
888               //
889               // String-related functions
890               //
891               ///////////////////////////////////////////////////////////////////////////////
892               
893               Boolean operator==(const String& str1, const String& str2)
894               {
895                   return String::equal(str1, str2);
896               }
897               
898               Boolean operator==(const String& str1, const char* str2)
899               {
900                   return String::equal(str1, str2);
901               }
902               
903               Boolean operator==(const char* str1, const String& str2)
904               {
905                   return String::equal(str1, str2);
906 kumpf    1.39 }
907               
908               Boolean operator!=(const String& str1, const String& str2)
909               {
910                   return !String::equal(str1, str2);
911               }
912               
913 kumpf    1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
914 kumpf    1.39 {
915 david    1.72 
916 david    1.69 #if defined(PEGASUS_OS_OS400)
917 david    1.93     CString cstr = str.getCString();
918 david    1.69     const char* utf8str = cstr;
919               
920                   os << utf8str;
921               
922 humberto 1.76 #elif defined(PEGASUS_HAS_ICU)
923 humberto 1.83 	if(os == cout || os == cerr){
924               	    char *buf = NULL;
925                   	const int size = str.size() * 6;
926                   	UnicodeString UniStr((const UChar *)str.getChar16Data(), (int32_t)str.size());
927                   	Uint32 bufsize = UniStr.extract(0,size,buf);
928                   
929                   	buf = new char[bufsize+1];
930                   	UniStr.extract(0,bufsize,buf);
931                   	os << buf;
932                   	os.flush();
933                   	delete [] buf;
934               	}else{
935 david    1.93 		CString cstr = str.getCString();
936 humberto 1.83     	const char* utf8str = cstr;
937                   	os << utf8str;
938               	}
939 humberto 1.76 	
940 david    1.69 #else
941 humberto 1.83     	for (Uint32 i = 0, n = str.size(); i < n; i++)
942                   	{
943                       	Uint16 code = str[i];
944 david    1.69 
945 humberto 1.83         	if (code > 0 && code <= PEGASUS_MAX_PRINTABLE_CHAR)
946                       	{
947                          	 os << char(code);
948                      	 	}
949                       	else
950                       	{
951                           	// Print in hex format:
952                           	char buffer[8];
953                           	sprintf(buffer, "\\x%04X", code);
954                           	os << buffer;
955                       	}
956                   	}
957 david    1.69 #endif // End of PEGASUS_HAS_ICU #else leg.
958 kumpf    1.39 
959                   return os;
960               }
961               
962               String operator+(const String& str1, const String& str2)
963               {
964                   return String(str1).append(str2);
965               }
966               
967               Boolean operator<(const String& str1, const String& str2)
968               {
969 kumpf    1.43     return String::compare(str1, str2) < 0;
970 kumpf    1.39 }
971               
972               Boolean operator<=(const String& str1, const String& str2)
973               {
974 kumpf    1.43     return String::compare(str1, str2) <= 0;
975 kumpf    1.39 }
976               
977               Boolean operator>(const String& str1, const String& str2)
978               {
979 kumpf    1.43     return String::compare(str1, str2) > 0;
980 kumpf    1.39 }
981               
982               Boolean operator>=(const String& str1, const String& str2)
983               {
984 kumpf    1.43     return String::compare(str1, str2) >= 0;
985 kumpf    1.39 }
986               
987 mike     1.27 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2