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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2