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

Diff for /pegasus/src/Pegasus/Common/String.cpp between version 1.111.2.6 and 1.138.2.1

version 1.111.2.6, 2005/09/29 15:10:55 version 1.138.2.1, 2013/06/03 22:35:13
Line 1 
Line 1 
 //%2005////////////////////////////////////////////////////////////////////////  //%LICENSE////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development  // Licensed to The Open Group (TOG) under one or more contributor license
 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.  // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;  // this work for additional information regarding copyright ownership.
 // IBM Corp.; EMC Corporation, The Open Group.  // Each contributor licenses this file to you under the OpenPegasus Open
 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;  // Source License; you may not use this file except in compliance with the
 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.  // License.
 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;  
 // EMC Corporation; VERITAS Software Corporation; The Open Group.  
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy  // Permission is hereby granted, free of charge, to any person obtaining a
 // of this software and associated documentation files (the "Software"), to  // copy of this software and associated documentation files (the "Software"),
 // deal in the Software without restriction, including without limitation the  // to deal in the Software without restriction, including without limitation
 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 // sell copies of the Software, and to permit persons to whom the Software is  // and/or sell copies of the Software, and to permit persons to whom the
 // furnished to do so, subject to the following conditions:  // Software is furnished to do so, subject to the following conditions:
 // //
 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN  // The above copyright notice and this permission notice shall be included
 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED  // in all copies or substantial portions of the Software.
 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT  
 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  
 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT  
 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  
 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
 // //
 //==============================================================================  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  //////////////////////////////////////////////////////////////////////////
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #define PEGASUS_USE_INTERNAL_INLINES  #include <Pegasus/Common/PegasusAssert.h>
 #include "String.h"  #include <cstring>
 #include <cassert>  
 #include "InternalException.h" #include "InternalException.h"
 #include "CommonUTF.h"  #include "MessageLoader.h"
 #include "CharSet.h"  #include "StringRep.h"
  
 #ifdef PEGASUS_STRING_ENABLE_ICU  #ifdef PEGASUS_HAS_ICU
   # include <unicode/ures.h>
 #include <unicode/ustring.h> #include <unicode/ustring.h>
 #include <unicode/uchar.h> #include <unicode/uchar.h>
 #endif #endif
Line 47 
Line 45 
  
 //============================================================================== //==============================================================================
 // //
 // Compile-time switches (defined macros).  // Compile-time macros (undefined by default).
 //  
 //     PEGASUS_STRING_ENABLE_ICU -- enables use of ICU package.  
 //  
 //     PEGASUS_STRING_NO_THROW -- suppresses throwing of exceptions  
 // //
 //     PEGASUS_STRING_NO_UTF8 -- don't generate slower UTF8 code. //     PEGASUS_STRING_NO_UTF8 -- don't generate slower UTF8 code.
 // //
 //     PEGASUS_USE_INTERNAL_INLINES -- enables internal inlining feature.  
 //  
 //============================================================================== //==============================================================================
  
 //============================================================================== //==============================================================================
Line 65 
Line 57 
 // //
 //============================================================================== //==============================================================================
  
 // Converts 16-bit characters to upper case.  // Note: this table is much faster than the system toupper(). Please do not
 inline Uint16 _to_upper(Uint16 x)  // change.
   
   const Uint8 _toUpperTable[256] =
   {
       0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
       0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
       0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
       0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
       0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
       0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
       0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
       0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
       0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
       0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
       0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
       0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
       0x60,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
       0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
       0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
       0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x7F,
       0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
       0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
       0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
       0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
       0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
       0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
       0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
       0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
       0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
       0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
       0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
       0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
       0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
       0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
       0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
       0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
   };
   
   // Note: this table is much faster than the system tolower(). Please do not
   // change.
   
   const Uint8 _toLowerTable[256] =
   {
       0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
       0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
       0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
       0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
       0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
       0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
       0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
       0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
       0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
       0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
       0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
       0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
       0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
       0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
       0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
       0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
       0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
       0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
       0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
       0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
       0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
       0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
       0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
       0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
       0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
       0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
       0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
       0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
       0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
       0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
       0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
       0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
   };
   
   // Converts 16-bit characters to upper case. This routine is faster than the
   // system toupper(). Please do not change.
   inline Uint16 _toUpper(Uint16 x)
 { {
     return (x & 0xFF00) ? x : CharSet::to_upper(x);      return (x & 0xFF00) ? x : _toUpperTable[x];
 } }
  
 // Converts 16-bit characters to lower case.  // Converts 16-bit characters to lower case. This routine is faster than the
 inline Uint16 _to_lower(Uint16 x)  // system toupper(). Please do not change.
   inline Uint16 _toLower(Uint16 x)
 { {
     return (x & 0xFF00) ? x : CharSet::to_lower(x);      return (x & 0xFF00) ? x : _toLowerTable[x];
 } }
  
 // Rounds x to the next power of two (or just returns 8 if x < 8).  // Rounds x up to the nearest power of two (or just returns 8 if x < 8).
 static Uint32 _next_pow_2(Uint32 x)  static Uint32 _roundUpToPow2(Uint32 x)
 { {
       // Check for potential overflow in x
       PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
   
     if (x < 8)     if (x < 8)
         return 8;         return 8;
  
Line 94 
Line 169 
     return x;     return x;
 } }
  
 template<class P, class Q>  
 static void _copy(P* p, const Q* q, size_t n)  
 {  
     // Use loop unrolling.  
   
     while (n >= 8)  
     {  
         p[0] = q[0];  
         p[1] = q[1];  
         p[2] = q[2];  
         p[3] = q[3];  
         p[4] = q[4];  
         p[5] = q[5];  
         p[6] = q[6];  
         p[7] = q[7];  
         p += 8;  
         q += 8;  
         n -= 8;  
     }  
   
     while (n >= 4)  
     {  
         p[0] = q[0];  
         p[1] = q[1];  
         p[2] = q[2];  
         p[3] = q[3];  
         p += 4;  
         q += 4;  
         n -= 4;  
     }  
   
     while (n--)  
         *p++ = *q++;  
 }  
   
 static Uint16* _find(const Uint16* s, size_t n, Uint16 c) static Uint16* _find(const Uint16* s, size_t n, Uint16 c)
 { {
       // The following employs loop unrolling for efficiency. Please do not
       // eliminate.
   
     while (n >= 4)     while (n >= 4)
     {     {
         if (s[0] == c)         if (s[0] == c)
Line 187 
Line 230 
     return 0;     return 0;
 } }
  
 static int _compare_no_utf8(const Uint16* s1, const char* s2)  #ifdef PEGASUS_STRING_NO_UTF8
   static int _compareNoUTF8(const Uint16* s1, const char* s2)
 { {
     Uint16 c1;     Uint16 c1;
     Uint16 c2;     Uint16 c2;
Line 204 
Line 248 
  
     return c1 - c2;     return c1 - c2;
 } }
   #endif
 static int _compare(const Uint16* s1, const Uint16* s2, size_t n)  
 {  
     // This should only be called when s1 and s2 have the same length.  
   
     while (n-- && (*s1++ - *s2++) == 0)  
         ;  
   
     return s1[-1] - s2[-1];  
 }  
  
 static inline void _copy(Uint16* s1, const Uint16* s2, size_t n) static inline void _copy(Uint16* s1, const Uint16* s2, size_t n)
 { {
     memcpy(s1, s2, n * sizeof(Uint16));     memcpy(s1, s2, n * sizeof(Uint16));
 } }
  
 void String_throw_out_of_bounds()  void StringThrowOutOfBounds()
 { {
     throw IndexOutOfBoundsException();     throw IndexOutOfBoundsException();
 } }
  
 #ifdef PEGASUS_STRING_NO_THROW  inline void _checkNullPointer(const void* ptr)
 # define _check_null_pointer(ARG) /* empty */  
 #else  
 template<class T>  
 inline void _check_null_pointer(const T* ptr)  
 { {
     if (!ptr)     if (!ptr)
         throw NullPointer();         throw NullPointer();
 } }
 #endif  
  
 static size_t _copy_from_utf8(Uint16* dest, const char* src, size_t n)  #define BADUTF8_MAX_CLEAR_CHAR 40
   #define BADUTF8_MAX_CHAR_TO_HEX 10
   
   static void _formatBadUTF8Chars(
       char* buffer,
       Uint32 index,
       const char* q,
       size_t n )
 { {
     Uint16* p = dest;  
     const Uint8* q = (const Uint8*)src;  
  
     // Process leading 7-bit ASCII characters (to avoid UTF8 overhead below      char tmp[20];
     // this loop). Use factor-four loop-unrolling.      const char* start;
  
     while (n >= 4 && q[0] < 128 && q[1] < 128 && q[2] < 128 && q[3] < 128)      size_t clearChar =
     {          (( index < BADUTF8_MAX_CLEAR_CHAR ) ? index : BADUTF8_MAX_CLEAR_CHAR );
         p[0] = q[0];      size_t charToHex =
         p[1] = q[1];          ((n-index-1) < BADUTF8_MAX_CHAR_TO_HEX ?
         p[2] = q[2];              (n-index-1) : BADUTF8_MAX_CHAR_TO_HEX );
         p[3] = q[3];  
         p += 4;  
         q += 4;  
         n -= 4;  
     }  
  
     switch (n)      if (index < BADUTF8_MAX_CLEAR_CHAR)
     {  
         case 0:  
             return p - dest;  
         case 1:  
             if (q[0] < 128)  
             {             {
                 p[0] = q[0];          start = q;
                 return p + 1 - dest;      } else
             }  
             break;  
         case 2:  
             if (q[0] < 128 && q[1] < 128)  
             {  
                 p[0] = q[0];  
                 p[1] = q[1];  
                 return p + 2 - dest;  
             }  
             break;  
         case 3:  
             if (q[0] < 128 && q[1] < 128 && q[2] < 128)  
             {             {
                 p[0] = q[0];          start = &(q[ index - BADUTF8_MAX_CLEAR_CHAR]);
                 p[1] = q[1];  
                 p[2] = q[2];  
                 return p + 3 - dest;  
             }  
             break;  
     }     }
  
     // Process remaining characters.      // Intialize the buffer with the first character as '\0' to be able to use
       // strnchat() and strcat()
     while (n)      buffer[0] = 0;
       // Start the buffer with the valid UTF8 chars
       strncat(buffer,start,clearChar);
       for (size_t i = clearChar, j = 0; j <= charToHex; i++,j++ )
     {     {
         // Optimize for 7-bit ASCII case.          tmp[0] = 0;
           sprintf(&(tmp[0])," 0x%02X",(Uint8)start[i]);
           strncat(buffer,&(tmp[0]),5);
       }
  
         if (*q < 128)  
         {  
             *p++ = *q++;  
             n--;  
         }         }
         else  
         {  
             Uint8 c = UTF_8_COUNT_TRAIL_BYTES(*q) + 1;  
  
             if (c > n || !isValid_U8(q, c) ||  static void _StringThrowBadUTF8(Uint32 index, const char* q, size_t n)
                 UTF8toUTF16(&q, q + c, &p, p + n) != 0)  
             {             {
                 throw Exception("Bad UTF8 encoding");      char buffer[1024];
             }  
  
             n -= c;      _formatBadUTF8Chars(&(buffer[0]),index,q,n);
         }  
     }      MessageLoaderParms parms(
           "Common.String.BAD_UTF8_LONG",
           "The byte sequence starting at index $0 "
           "is not valid UTF-8 encoding: $1",
           index,buffer);
  
     return p - dest;      throw Exception(parms);
 } }
  
 // Note: dest must be at least three times src (plus an extra byte for // Note: dest must be at least three times src (plus an extra byte for
 // terminator). // terminator).
 static inline size_t _copy_to_utf8(char* dest, const Uint16* src, size_t n)  static inline size_t _copyToUTF8(char* dest, const Uint16* src, size_t n)
 { {
       // The following employs loop unrolling for efficiency. Please do not
       // eliminate.
   
     const Uint16* q = src;     const Uint16* q = src;
     Uint8* p = (Uint8*)dest;     Uint8* p = (Uint8*)dest;
  
Line 368 
Line 380 
     return p - (Uint8*)dest;     return p - (Uint8*)dest;
 } }
  
 static inline size_t _convert(Uint16* p, const char* q, size_t n)  
 {  
 #ifdef PEGASUS_STRING_NO_UTF8  
     _copy(p, q, n);  
     return n;  
 #else  
     return _copy_from_utf8(p, q, n);  
 #endif  
 }  
   
 //============================================================================== //==============================================================================
 // //
 // class CString // class CString
Line 421 
Line 423 
 // //
 //============================================================================== //==============================================================================
  
 StringRep StringRep::_empty_rep;  StringRep StringRep::_emptyRep;
  
 inline StringRep* StringRep::alloc(size_t cap) inline StringRep* StringRep::alloc(size_t cap)
 { {
       // Check for potential overflow in cap
       PEGASUS_CHECK_CAPACITY_OVERFLOW(cap);
   
     StringRep* rep = (StringRep*)::operator new(     StringRep* rep = (StringRep*)::operator new(
         sizeof(StringRep) + cap * sizeof(Uint16));         sizeof(StringRep) + cap * sizeof(Uint16));
     rep->cap = cap;     rep->cap = cap;
     Atomic_create(&rep->refs, 1);      new(&rep->refs) AtomicInt(1);
  
     return rep;     return rep;
 } }
  
 static inline void _reserve(StringRep*& rep, Uint32 cap) static inline void _reserve(StringRep*& rep, Uint32 cap)
 { {
     if (cap > rep->cap || Atomic_get(&rep->refs) != 1)      if (cap > rep->cap || rep->refs.get() != 1)
     {     {
         size_t n = _next_pow_2(cap);          size_t n = _roundUpToPow2(cap);
         StringRep* new_rep = StringRep::alloc(n);          StringRep* newRep = StringRep::alloc(n);
         new_rep->size = rep->size;          newRep->size = rep->size;
         _copy(new_rep->data, rep->data, rep->size + 1);          _copy(newRep->data, rep->data, rep->size + 1);
         StringRep::unref(rep);         StringRep::unref(rep);
         rep = new_rep;          rep = newRep;
     }     }
 } }
  
Line 455 
Line 460 
     return rep;     return rep;
 } }
  
 StringRep* StringRep::copy_on_write(StringRep* rep)  StringRep* StringRep::copyOnWrite(StringRep* rep)
 { {
     // Return a new copy of rep. Release rep.     // Return a new copy of rep. Release rep.
  
     StringRep* new_rep = StringRep::alloc(rep->size);      StringRep* newRep = StringRep::alloc(rep->size);
     new_rep->size = rep->size;      newRep->size = rep->size;
     _copy(new_rep->data, rep->data, rep->size);      _copy(newRep->data, rep->data, rep->size);
     new_rep->data[new_rep->size] = '\0';      newRep->data[newRep->size] = '\0';
     StringRep::unref(rep);     StringRep::unref(rep);
     return new_rep;      return newRep;
 } }
  
 StringRep* StringRep::create(const char* data, size_t size) StringRep* StringRep::create(const char* data, size_t size)
 { {
     StringRep* rep = StringRep::alloc(size);     StringRep* rep = StringRep::alloc(size);
     rep->size = _convert((Uint16*)rep->data, data, size);      size_t utf8_error_index;
     rep->data[rep->size] = '\0';      rep->size = _convert((Uint16*)rep->data, data, size, utf8_error_index);
  
     return rep;      if (rep->size == size_t(-1))
       {
           StringRep::free(rep);
           _StringThrowBadUTF8((Uint32)utf8_error_index, data,size);
 } }
  
 StringRep* StringRep::createASCII7(const char* data, size_t size)      rep->data[rep->size] = '\0';
 {  
     StringRep* rep = StringRep::alloc(size);  
     _copy((Uint16*)rep->data, data, size);  
     rep->data[rep->size = size] = '\0';  
     return rep;     return rep;
 } }
  
Line 493 
Line 498 
     while (*end++)     while (*end++)
         ;         ;
  
     return end - str - 1;      return (Uint32)(end - str - 1);
 } }
  
 //============================================================================== //==============================================================================
Line 506 
Line 511 
  
 String::String(const String& str, Uint32 n) String::String(const String& str, Uint32 n)
 { {
     _check_bounds(n, str._rep->size);      _checkBounds(n, str._rep->size);
     _rep = StringRep::create(str._rep->data, n);     _rep = StringRep::create(str._rep->data, n);
 } }
  
 String::String(const Char16* str) String::String(const Char16* str)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
     _rep = StringRep::create((Uint16*)str, StringRep::length((Uint16*)str));     _rep = StringRep::create((Uint16*)str, StringRep::length((Uint16*)str));
 } }
  
 String::String(const Char16* str, Uint32 n) String::String(const Char16* str, Uint32 n)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
     _rep = StringRep::create((Uint16*)str, n);     _rep = StringRep::create((Uint16*)str, n);
 } }
  
 String::String(const char* str) String::String(const char* str)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
     _rep = StringRep::create(str, strlen(str));  
 }  
  
 String::String(const char* str, String::ASCII7Tag tag)      // Set this just in case create() throws an exception.
 {      _rep = &StringRep::_emptyRep;
     _check_null_pointer(str);      _rep = StringRep::create(str, strlen(str));
     _rep = StringRep::createASCII7(str, strlen(str));  
 } }
  
 String::String(const char* str, Uint32 n) String::String(const char* str, Uint32 n)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
     _rep = StringRep::create(str, n);  
 }  
  
 String::String(const char* str, size_t n, String::ASCII7Tag tag)      // Set this just in case create() throws an exception.
 {      _rep = &StringRep::_emptyRep;
     _check_null_pointer(str);      _rep = StringRep::create(str, n);
     _rep = StringRep::createASCII7(str, n);  
 } }
  
 String::String(const String& s1, const String& s2) String::String(const String& s1, const String& s2)
Line 560 
Line 559 
  
 String::String(const String& s1, const char* s2) String::String(const String& s1, const char* s2)
 { {
     _check_null_pointer(s2);      _checkNullPointer(s2);
     size_t n1 = s1._rep->size;     size_t n1 = s1._rep->size;
     size_t n2 = strlen(s2);     size_t n2 = strlen(s2);
     _rep = StringRep::alloc(n1 + n2);     _rep = StringRep::alloc(n1 + n2);
     _copy(_rep->data, s1._rep->data, n1);     _copy(_rep->data, s1._rep->data, n1);
     _rep->size = n1 + _convert((Uint16*)_rep->data + n1, s2, n2);      size_t utf8_error_index;
       size_t tmp = _convert((Uint16*)_rep->data + n1, s2, n2, utf8_error_index);
   
       if (tmp == size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8((Uint32)utf8_error_index,s2,n2);
       }
   
       _rep->size = n1 + tmp;
     _rep->data[_rep->size] = '\0';     _rep->data[_rep->size] = '\0';
 } }
  
 String::String(const char* s1, const String& s2) String::String(const char* s1, const String& s2)
 { {
     _check_null_pointer(s1);      _checkNullPointer(s1);
     size_t n1 = strlen(s1);     size_t n1 = strlen(s1);
     size_t n2 = s2._rep->size;     size_t n2 = s2._rep->size;
     _rep = StringRep::alloc(n1 + n2);     _rep = StringRep::alloc(n1 + n2);
     _rep->size = n2 + _convert((Uint16*)_rep->data, s1, n1);      size_t utf8_error_index;
       size_t tmp = _convert((Uint16*)_rep->data, s1, n1, utf8_error_index);
   
       if (tmp ==  size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8((Uint32)utf8_error_index,s1,n1);
       }
   
       _rep->size = n2 + tmp;
     _copy(_rep->data + n1, s2._rep->data, n2);     _copy(_rep->data + n1, s2._rep->data, n2);
     _rep->data[_rep->size] = '\0';     _rep->data[_rep->size] = '\0';
 } }
Line 593 
Line 612 
  
 String& String::assign(const Char16* str, Uint32 n) String& String::assign(const Char16* str, Uint32 n)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
  
     if (n > _rep->cap || Atomic_get(&_rep->refs) != 1)      if (n > _rep->cap || _rep->refs.get() != 1)
     {     {
         StringRep::unref(_rep);         StringRep::unref(_rep);
         _rep = StringRep::alloc(n);         _rep = StringRep::alloc(n);
Line 610 
Line 629 
  
 String& String::assign(const char* str, Uint32 n) String& String::assign(const char* str, Uint32 n)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
  
     if (n > _rep->cap || Atomic_get(&_rep->refs) != 1)      if (n > _rep->cap || _rep->refs.get() != 1)
     {     {
         StringRep::unref(_rep);         StringRep::unref(_rep);
         _rep = StringRep::alloc(n);         _rep = StringRep::alloc(n);
     }     }
  
     _rep->size = _convert(_rep->data, str, n);      size_t utf8_error_index;
     _rep->data[_rep->size] = 0;      _rep->size = _convert(_rep->data, str, n, utf8_error_index);
  
     return *this;      if (_rep->size ==  size_t(-1))
 }  
   
 String& String::assignASCII7(const char* str, Uint32 n)  
 {  
     _check_null_pointer(str);  
   
     if (n > _rep->cap || Atomic_get(&_rep->refs) != 1)  
     {     {
         StringRep::unref(_rep);          StringRep::free(_rep);
         _rep = StringRep::alloc(n);          _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8((Uint32)utf8_error_index,str,n);
     }     }
  
     _copy(_rep->data, str, n);      _rep->data[_rep->size] = 0;
     _rep->data[_rep->size = n] = 0;  
  
     return *this;     return *this;
 } }
Line 644 
Line 656 
 { {
     if (_rep->size)     if (_rep->size)
     {     {
         if (Atomic_get(&_rep->refs) == 1)          if (_rep->refs.get() == 1)
           {
             _rep->size = 0;             _rep->size = 0;
               _rep->data[0] = '\0';
           }
         else         else
         {         {
             StringRep::unref(_rep);             StringRep::unref(_rep);
             _rep = &StringRep::_empty_rep;              _rep = &StringRep::_emptyRep;
         }         }
     }     }
 } }
Line 661 
Line 676 
  
 CString String::getCString() const CString String::getCString() const
 { {
       // A UTF8 string can have three times as many characters as its UTF16
       // counterpart, so we allocate extra memory for the worst case. In the
       // best case, we may need only one third of the memory allocated. But
       // downsizing the string afterwards is expensive and unecessary since
       // CString objects are usually short-lived (disappearing after only a few
       // instructions). CString objects are typically created on the stack as
       // means to obtain a char* pointer.
   
 #ifdef PEGASUS_STRING_NO_UTF8 #ifdef PEGASUS_STRING_NO_UTF8
     char* str = (char*)operator new(_rep->size + 1);     char* str = (char*)operator new(_rep->size + 1);
     _copy(str, _rep->data, _rep->size);     _copy(str, _rep->data, _rep->size);
     str[_rep->size] = '\0';     str[_rep->size] = '\0';
     return CString(str);     return CString(str);
 #else #else
     Uint32 n = 3 * _rep->size;      Uint32 n = (Uint32)(3 * _rep->size);
     char* str = (char*)operator new(n + 1);     char* str = (char*)operator new(n + 1);
     size_t size = _copy_to_utf8(str, _rep->data, _rep->size);      size_t size = _copyToUTF8(str, _rep->data, _rep->size);
     str[size] = '\0';     str[size] = '\0';
     return CString(str);     return CString(str);
 #endif #endif
Line 677 
Line 700 
  
 String& String::append(const Char16* str, Uint32 n) String& String::append(const Char16* str, Uint32 n)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
  
     size_t old_size = _rep->size;      size_t oldSize = _rep->size;
     size_t new_size = old_size + n;      size_t newSize = oldSize + n;
     _reserve(_rep, new_size);      _reserve(_rep, (Uint32)newSize);
     _copy(_rep->data + old_size, (Uint16*)str, n);      _copy(_rep->data + oldSize, (Uint16*)str, n);
     _rep->size = new_size;      _rep->size = newSize;
     _rep->data[new_size] = '\0';      _rep->data[newSize] = '\0';
  
     return *this;     return *this;
 } }
  
 String& String::append(const String& str) String& String::append(const String& str)
 { {
     return append((Char16*)str._rep->data, str._rep->size);      return append((Char16*)(&(str._rep->data[0])), (Uint32)str._rep->size);
 } }
  
 String& String::append(const char* str, Uint32 size) String& String::append(const char* str, Uint32 size)
 { {
     _check_null_pointer(str);      _checkNullPointer(str);
  
     size_t old_size = _rep->size;      size_t oldSize = _rep->size;
     size_t cap = old_size + size;      size_t cap = oldSize + size;
  
     _reserve(_rep, cap);      _reserve(_rep, (Uint32)cap);
     _rep->size += _convert((Uint16*)_rep->data + old_size, str, size);      size_t utf8_error_index;
       size_t tmp = _convert(
           (Uint16*)_rep->data + oldSize, str, size, utf8_error_index);
   
       if (tmp ==  size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8((Uint32)utf8_error_index,str,size);
       }
   
       _rep->size += tmp;
     _rep->data[_rep->size] = '\0';     _rep->data[_rep->size] = '\0';
  
     return *this;     return *this;
Line 711 
Line 745 
 void String::remove(Uint32 index, Uint32 n) void String::remove(Uint32 index, Uint32 n)
 { {
     if (n == PEG_NOT_FOUND)     if (n == PEG_NOT_FOUND)
         n = _rep->size - index;          n = (Uint32)(_rep->size - index);
  
     _check_bounds(index + n, _rep->size);      _checkBounds(index + n, _rep->size);
  
     if (Atomic_get(&_rep->refs) != 1)      if (_rep->refs.get() != 1)
         _rep = StringRep::copy_on_write(_rep);          _rep = StringRep::copyOnWrite(_rep);
  
     assert(index + n <= _rep->size);      PEGASUS_ASSERT(index + n <= _rep->size);
  
     size_t rem = _rep->size - (index + n);     size_t rem = _rep->size - (index + n);
     Uint16* data = _rep->data;     Uint16* data = _rep->data;
Line 738 
Line 772 
     if (index < _rep->size)     if (index < _rep->size)
     {     {
         if (n == PEG_NOT_FOUND || n > _rep->size - index)         if (n == PEG_NOT_FOUND || n > _rep->size - index)
             n = _rep->size - index;              n = (Uint32)(_rep->size - index);
  
         return String((Char16*)_rep->data + index, n);          return String((Char16*)(_rep->data + index), n);
     }     }
  
     return String();     return String();
Line 751 
Line 785 
     Uint16* p = (Uint16*)_find(_rep->data, _rep->size, c);     Uint16* p = (Uint16*)_find(_rep->data, _rep->size, c);
  
     if (p)     if (p)
         return p - _rep->data;          return static_cast<Uint32>(p - _rep->data);
  
     return PEG_NOT_FOUND;     return PEG_NOT_FOUND;
 } }
  
 Uint32 String::find(Uint32 index, Char16 c) const Uint32 String::find(Uint32 index, Char16 c) const
 { {
     _check_bounds(index, _rep->size);      _checkBounds(index, _rep->size);
  
     if (index >= _rep->size)     if (index >= _rep->size)
         return PEG_NOT_FOUND;         return PEG_NOT_FOUND;
Line 766 
Line 800 
     Uint16* p = (Uint16*)_find(_rep->data + index, _rep->size - index, c);     Uint16* p = (Uint16*)_find(_rep->data + index, _rep->size - index, c);
  
     if (p)     if (p)
         return p - _rep->data;          return static_cast<Uint32>(p - _rep->data);
  
     return PEG_NOT_FOUND;     return PEG_NOT_FOUND;
 } }
  
 Uint32 String::_find_aux(const Char16* s, Uint32 n) const  Uint32 StringFindAux(
       const StringRep* _rep, const Char16* s, Uint32 n)
 { {
     _check_null_pointer(s);      _checkNullPointer(s);
  
     const Uint16* data = _rep->data;     const Uint16* data = _rep->data;
     size_t rem = _rep->size;     size_t rem = _rep->size;
Line 786 
Line 821 
             break;             break;
  
         if (memcmp(p, s, n * sizeof(Uint16)) == 0)         if (memcmp(p, s, n * sizeof(Uint16)) == 0)
             return p - _rep->data;              return static_cast<Uint32>(p - _rep->data);
  
         p++;         p++;
         rem -= p - data;         rem -= p - data;
Line 798 
Line 833 
  
 Uint32 String::find(const char* s) const Uint32 String::find(const char* s) const
 { {
     _check_null_pointer(s);      _checkNullPointer(s);
  
     // Note: could optimize away creation of temporary, but this is rarely     // Note: could optimize away creation of temporary, but this is rarely
     // called.     // called.
Line 814 
Line 849 
     while (q != p)     while (q != p)
     {     {
         if (*--q == x)         if (*--q == x)
             return q - p;              return static_cast<Uint32>(q - p);
     }     }
  
     return PEG_NOT_FOUND;     return PEG_NOT_FOUND;
Line 822 
Line 857 
  
 void String::toLower() void String::toLower()
 { {
 #ifdef PEGASUS_STRING_ENABLE_ICU  #ifdef PEGASUS_HAS_ICU
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
           if (_rep->refs.get() != 1)
               _rep = StringRep::copyOnWrite(_rep);
   
           // This will do a locale-insensitive, but context-sensitive convert.
           // Since context-sensitive casing looks at adjacent chars, this
           // prevents optimizations where the us-ascii is converted before
           // calling ICU.
           // The string may shrink or expand after the convert.
   
         //// First calculate size of resulting string. u_strToLower() returns         //// First calculate size of resulting string. u_strToLower() returns
         //// only the size when zero is passed as the destination size argument.         //// only the size when zero is passed as the destination size argument.
  
         UErrorCode err = U_ZERO_ERROR;         UErrorCode err = U_ZERO_ERROR;
  
         int32_t new_size = u_strToLower(          int32_t newSize = u_strToLower(
             NULL, 0, (UChar*)_rep->data, _rep->size, NULL, &err);             NULL, 0, (UChar*)_rep->data, _rep->size, NULL, &err);
  
           err = U_ZERO_ERROR;
   
         //// Reserve enough space for the result.         //// Reserve enough space for the result.
  
         if ((Uint32)new_size > _rep->cap)          if ((Uint32)newSize > _rep->cap)
             _reserve(_rep, new_size);              _reserve(_rep, newSize);
  
         //// Perform the conversion (overlapping buffers are allowed).         //// Perform the conversion (overlapping buffers are allowed).
  
         u_strToLower((UChar*)_rep->data, new_size,          u_strToLower((UChar*)_rep->data, newSize,
             (UChar*)_rep->data, _rep->size, NULL, &err);             (UChar*)_rep->data, _rep->size, NULL, &err);
  
         _rep->size = new_size;          _rep->size = newSize;
           return;
     }     }
  
 #endif /* PEGASUS_STRING_ENABLE_ICU */  #endif /* PEGASUS_HAS_ICU */
  
     if (Atomic_get(&_rep->refs) != 1)      if (_rep->refs.get() != 1)
         _rep = StringRep::copy_on_write(_rep);          _rep = StringRep::copyOnWrite(_rep);
  
     Uint16* p = _rep->data;     Uint16* p = _rep->data;
     size_t n = _rep->size;     size_t n = _rep->size;
Line 858 
Line 905 
     for (; n--; p++)     for (; n--; p++)
     {     {
         if (!(*p & 0xFF00))         if (!(*p & 0xFF00))
             *p = _to_lower(*p);              *p = _toLower(*p);
     }     }
 } }
  
 void String::toUpper() void String::toUpper()
 { {
 #ifdef PEGASUS_STRING_ENABLE_ICU  #ifdef PEGASUS_HAS_ICU
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
           if (_rep->refs.get() != 1)
               _rep = StringRep::copyOnWrite(_rep);
   
           // This will do a locale-insensitive, but context-sensitive convert.
           // Since context-sensitive casing looks at adjacent chars, this
           // prevents optimizations where the us-ascii is converted before
           // calling ICU.
           // The string may shrink or expand after the convert.
   
         //// First calculate size of resulting string. u_strToUpper() returns         //// First calculate size of resulting string. u_strToUpper() returns
         //// only the size when zero is passed as the destination size argument.         //// only the size when zero is passed as the destination size argument.
  
         UErrorCode err = U_ZERO_ERROR;         UErrorCode err = U_ZERO_ERROR;
  
         int32_t new_size = u_strToUpper(          int32_t newSize = u_strToUpper(
             NULL, 0, (UChar*)_rep->data, _rep->size, NULL, &err);             NULL, 0, (UChar*)_rep->data, _rep->size, NULL, &err);
  
           err = U_ZERO_ERROR;
   
         //// Reserve enough space for the result.         //// Reserve enough space for the result.
  
         if ((Uint32)new_size > _rep->cap)          if ((Uint32)newSize > _rep->cap)
             _reserve(_rep, new_size);              _reserve(_rep, newSize);
  
         //// Perform the conversion (overlapping buffers are allowed).         //// Perform the conversion (overlapping buffers are allowed).
  
         u_strToUpper((UChar*)_rep->data, new_size,          u_strToUpper((UChar*)_rep->data, newSize,
             (UChar*)_rep->data, _rep->size, NULL, &err);             (UChar*)_rep->data, _rep->size, NULL, &err);
  
         _rep->size = new_size;          _rep->size = newSize;
   
           return;
     }     }
  
 #endif /* PEGASUS_STRING_ENABLE_ICU */  #endif /* PEGASUS_HAS_ICU */
  
     if (Atomic_get(&_rep->refs) != 1)      if (_rep->refs.get() != 1)
         _rep = StringRep::copy_on_write(_rep);          _rep = StringRep::copyOnWrite(_rep);
  
     Uint16* p = _rep->data;     Uint16* p = _rep->data;
     size_t n = _rep->size;     size_t n = _rep->size;
  
     for (; n--; p++)     for (; n--; p++)
         *p = _to_upper(*p);          *p = _toUpper(*p);
 } }
  
 int String::compare(const String& s1, const String& s2, Uint32 n) int String::compare(const String& s1, const String& s2, Uint32 n)
 { {
     assert(n <= s1._rep->size);      const Uint16* p1 = s1._rep->data;
     assert(n <= s2._rep->size);      const Uint16* p2 = s2._rep->data;
  
     // Ignoring error in which n is greater than s1.size() or s2.size()      while (n--)
     return _compare(s1._rep->data, s2._rep->data, n);      {
           int r = *p1++ - *p2++;
           if (r)
           {
               return r;
           }
           else if (!p1[-1])
           {
               // We must have encountered a null terminator in both s1 and s2
               return 0;
           }
       }
       return 0;
 } }
  
 int String::compare(const String& s1, const String& s2) int String::compare(const String& s1, const String& s2)
Line 917 
Line 989 
  
 int String::compare(const String& s1, const char* s2) int String::compare(const String& s1, const char* s2)
 { {
     _check_null_pointer(s2);      _checkNullPointer(s2);
  
 #ifdef PEGASUS_STRING_NO_UTF8 #ifdef PEGASUS_STRING_NO_UTF8
     return _compare_no_utf8(s1._rep->data, s2);      return _compareNoUTF8(s1._rep->data, s2);
 #else #else
     // ATTN: optimize this!     // ATTN: optimize this!
     return String::compare(s1, String(s2));     return String::compare(s1, String(s2));
Line 929 
Line 1001 
  
 int String::compareNoCase(const String& str1, const String& str2) int String::compareNoCase(const String& str1, const String& str2)
 { {
 #ifdef PEGASUS_STRING_ENABLE_ICU  #ifdef PEGASUS_HAS_ICU
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
         return  u_strcasecmp(         return  u_strcasecmp(
             str1._rep->data, str2._rep->data, U_FOLD_CASE_DEFAULT);              (const UChar*)str1._rep->data,
               (const UChar*)str2._rep->data,
               U_FOLD_CASE_DEFAULT
               );
     }     }
  
 #endif /* PEGASUS_STRING_ENABLE_ICU */  #endif /* PEGASUS_HAS_ICU */
  
     const Uint16* s1 = str1._rep->data;     const Uint16* s1 = str1._rep->data;
     const Uint16* s2 = str2._rep->data;     const Uint16* s2 = str2._rep->data;
  
     while (*s1 && *s2)     while (*s1 && *s2)
     {     {
         int r = _to_lower(*s1++) - _to_lower(*s2++);          int r = _toLower(*s1++) - _toLower(*s2++);
  
         if (r)         if (r)
             return r;             return r;
Line 958 
Line 1033 
     return 0;     return 0;
 } }
  
 Boolean String::equalNoCase_aux(const String& s1, const String& s2)  Boolean StringEqualNoCase(const String& s1, const String& s2)
 { {
 #ifdef PEGASUS_STRING_ENABLE_ICU  #ifdef PEGASUS_HAS_ICU
  
     return String::compareNoCase(s1, s2) == 0;     return String::compareNoCase(s1, s2) == 0;
  
 #else /* PEGASUS_STRING_ENABLE_ICU */  #else /* PEGASUS_HAS_ICU */
   
       // The following employs loop unrolling for efficiency. Please do not
       // eliminate.
  
     Uint16* p = (Uint16*)s1._rep->data;      Uint16* p = (Uint16*)s1.getChar16Data();
     Uint16* q = (Uint16*)s2._rep->data;      Uint16* q = (Uint16*)s2.getChar16Data();
     Uint32 n = s2._rep->size;      Uint32 n = s2.size();
  
     while (n >= 8)     while (n >= 8)
     {     {
         if (((p[0] - q[0]) && (_to_upper(p[0]) - _to_upper(q[0]))) ||          if (((p[0] - q[0]) && (_toUpper(p[0]) - _toUpper(q[0]))) ||
             ((p[1] - q[1]) && (_to_upper(p[1]) - _to_upper(q[1]))) ||              ((p[1] - q[1]) && (_toUpper(p[1]) - _toUpper(q[1]))) ||
             ((p[2] - q[2]) && (_to_upper(p[2]) - _to_upper(q[2]))) ||              ((p[2] - q[2]) && (_toUpper(p[2]) - _toUpper(q[2]))) ||
             ((p[3] - q[3]) && (_to_upper(p[3]) - _to_upper(q[3]))) ||              ((p[3] - q[3]) && (_toUpper(p[3]) - _toUpper(q[3]))) ||
             ((p[4] - q[4]) && (_to_upper(p[4]) - _to_upper(q[4]))) ||              ((p[4] - q[4]) && (_toUpper(p[4]) - _toUpper(q[4]))) ||
             ((p[5] - q[5]) && (_to_upper(p[5]) - _to_upper(q[5]))) ||              ((p[5] - q[5]) && (_toUpper(p[5]) - _toUpper(q[5]))) ||
             ((p[6] - q[6]) && (_to_upper(p[6]) - _to_upper(q[6]))) ||              ((p[6] - q[6]) && (_toUpper(p[6]) - _toUpper(q[6]))) ||
             ((p[7] - q[7]) && (_to_upper(p[7]) - _to_upper(q[7]))))              ((p[7] - q[7]) && (_toUpper(p[7]) - _toUpper(q[7]))))
         {         {
             return false;             return false;
         }         }
Line 991 
Line 1069 
  
     while (n >= 4)     while (n >= 4)
     {     {
         if (((p[0] - q[0]) && (_to_upper(p[0]) - _to_upper(q[0]))) ||          if (((p[0] - q[0]) && (_toUpper(p[0]) - _toUpper(q[0]))) ||
             ((p[1] - q[1]) && (_to_upper(p[1]) - _to_upper(q[1]))) ||              ((p[1] - q[1]) && (_toUpper(p[1]) - _toUpper(q[1]))) ||
             ((p[2] - q[2]) && (_to_upper(p[2]) - _to_upper(q[2]))) ||              ((p[2] - q[2]) && (_toUpper(p[2]) - _toUpper(q[2]))) ||
             ((p[3] - q[3]) && (_to_upper(p[3]) - _to_upper(q[3]))))              ((p[3] - q[3]) && (_toUpper(p[3]) - _toUpper(q[3]))))
         {         {
             return false;             return false;
         }         }
Line 1006 
Line 1084 
  
     while (n--)     while (n--)
     {     {
         if (((p[0] - q[0]) && (_to_upper(p[0]) - _to_upper(q[0]))))          if (((p[0] - q[0]) && (_toUpper(p[0]) - _toUpper(q[0]))))
             return false;             return false;
  
         p++;         p++;
Line 1015 
Line 1093 
  
     return true;     return true;
  
 #endif /* PEGASUS_STRING_ENABLE_ICU */  #endif /* PEGASUS_HAS_ICU */
 } }
  
 Boolean String::equalNoCase(const String& s1, const char* s2) Boolean String::equalNoCase(const String& s1, const char* s2)
 { {
     _check_null_pointer(s2);      _checkNullPointer(s2);
  
 #if defined(PEGASUS_STRING_ENABLE_ICU)  #if defined(PEGASUS_HAS_ICU)
  
     return String::equalNoCase(s1, String(s2));     return String::equalNoCase(s1, String(s2));
  
Line 1037 
Line 1115 
         if (!*p2)         if (!*p2)
             return false;             return false;
  
         if (_to_upper(*p1++) != CharSet::to_upper(int(*p2++)))          if (_toUpper(*p1++) != _toUpperTable[int(*p2++)])
             return false;             return false;
     }     }
  
       if (*p2)
           return false;
   
     return true;     return true;
  
 #else /* PEGASUS_STRING_ENABLE_ICU */  #else /* PEGASUS_HAS_ICU */
  
     // ATTN: optimize this!     // ATTN: optimize this!
     return String::equalNoCase(s1, String(s2));     return String::equalNoCase(s1, String(s2));
  
 #endif /* PEGASUS_STRING_ENABLE_ICU */  #endif /* PEGASUS_HAS_ICU */
 } }
  
 Boolean String::equal(const String& s1, const String& s2) Boolean String::equal(const String& s1, const String& s2)
 { {
     return s1._rep->size == s2._rep->size && memcmp(s1._rep->data,      return (s1._rep == s2._rep) ||
         s2._rep->data, s1._rep->size * sizeof(Uint16)) == 0;          ((s1._rep->size == s2._rep->size) &&
            memcmp(s1._rep->data,
                   s2._rep->data,
                   s1._rep->size * sizeof(Uint16)) == 0);
 } }
  
 Boolean String::equal(const String& s1, const char* s2) Boolean String::equal(const String& s1, const char* s2)
 { {
 #ifdef PEGASUS_STRING_NO_UTF8 #ifdef PEGASUS_STRING_NO_UTF8
  
     _check_null_pointer(s2);      _checkNullPointer(s2);
  
     const Uint16* p = (Uint16*)s1._rep->data;     const Uint16* p = (Uint16*)s1._rep->data;
     const char* q = s2;     const char* q = s2;
Line 1083 
Line 1167 
  
 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str) PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
 { {
 #if defined(PEGASUS_OS_OS400)  #if defined(PEGASUS_HAS_ICU)
   
     CString cstr = str.getCString();  
     const char* utf8str = cstr;  
     os << utf8str;  
   
 #elif defined(PEGASUS_STRING_ENABLE_ICU)  
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
Line 1103 
Line 1181 
         os << buf;         os << buf;
         os.flush();         os.flush();
         delete [] buf;         delete [] buf;
           return os;
     }     }
  
 #endif /* PEGASUS_OS_OS400 */  #endif  // PEGASUS_HAS_ICU
  
     for (Uint32 i = 0, n = str.size(); i < n; i++)     for (Uint32 i = 0, n = str.size(); i < n; i++)
     {     {
Line 1125 
Line 1204 
     return os;     return os;
 } }
  
 void String::_append_char_aux()  void StringAppendCharAux(StringRep*& _rep)
 { {
     StringRep* tmp;     StringRep* tmp;
  
Line 1145 
Line 1224 
     _rep = tmp;     _rep = tmp;
 } }
  
   void AssignASCII(String& s, const char* str, Uint32 n)
   {
       class StringLayout
       {
       public:
           StringRep* rep;
       };
   
       StringLayout* that = reinterpret_cast<StringLayout*>(&s);
   
       _checkNullPointer(str);
   
       if (n > that->rep->cap || that->rep->refs.get() != 1)
       {
           StringRep::unref(that->rep);
           that->rep = StringRep::alloc(n);
       }
   
       _copy(that->rep->data, str, n);
       that->rep->size = n;
       that->rep->data[that->rep->size] = 0;
   }
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END
  
 /* /*
Line 1168 
Line 1270 
         GCC Developers Summit). This reduced default construction to a simple         GCC Developers Summit). This reduced default construction to a simple
         pointer assignment.         pointer assignment.
  
             inline String::String() : _rep(&_empty_rep) { }              inline String::String() : _rep(&_emptyRep) { }
  
     5.  Implemented Uint16 versions of toupper() and tolower() using tables.     5.  Implemented Uint16 versions of toupper() and tolower() using tables.
         For example:         For example:
Line 1178 
Line 1280 
                 0,1,2,...255                 0,1,2,...255
             };             };
  
             inline Uint16 _to_upper(Uint16 x)              inline Uint16 _toUpper(Uint16 x)
             {             {
                 return (x & 0xFF00) ? x : _upper[x];                 return (x & 0xFF00) ? x : _upper[x];
             }             }
Line 1217 
Line 1319 
             String operator+(const String& s1, const char* s2)             String operator+(const String& s1, const char* s2)
             String operator+(const char* s1, const String& s2)             String operator+(const char* s1, const String& s2)
  
     7.  Optimized _next_pow_2(), used in rounding the capacity to the next      7.  Optimized _roundUpToPow2(), used in rounding the capacity to the next
         power of two (algorithm from the book "Hacker's Delight").         power of two (algorithm from the book "Hacker's Delight").
  
             static Uint32 _next_pow_2(Uint32 x)              static Uint32 _roundUpToPow2(Uint32 x)
             {             {
                 if (x < 8)                 if (x < 8)
                     return 8;                     return 8;
Line 1246 
Line 1348 
             }             }
  
     9.  Experimented to find the optimial initial size for a short string.     9.  Experimented to find the optimial initial size for a short string.
         Eight seems to offer the best tradoff between space and time.          Eight seems to offer the best tradeoff between space and time.
  
     10. Inlined all members of the Char16 class.     10. Inlined all members of the Char16 class.
  


Legend:
Removed from v.1.111.2.6  
changed lines
  Added in v.1.138.2.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2