(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.6.3 and 1.119.2.2

version 1.111.6.3, 2005/10/08 02:16:01 version 1.119.2.2, 2006/05/31 21:43:17
Line 1 
Line 1 
 //%2005////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
Line 8 
Line 8 
 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 // EMC Corporation; VERITAS Software Corporation; The Open Group. // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec 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 copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 27 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  // Author: Mike Brasher (mbrasher@austin.rr.com)
 // //
 // Modified By: // Modified By:
 //     Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) //     Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 //     Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#3297 //     Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#3297
 //     David Dillard, VERITAS Software Corp. (david.dillard@veritas.com)  //     David Dillard, Symantec Corp. (david_dillard@symantec.com)
 //     Mike Brasher (mike-brasher@austin.rr.com) //     Mike Brasher (mike-brasher@austin.rr.com)
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include <cassert>  #include <Pegasus/Common/PegasusAssert.h>
   #include <cstring>
 #include "InternalException.h" #include "InternalException.h"
 #include "CommonUTF.h" #include "CommonUTF.h"
 #include "MessageLoader.h" #include "MessageLoader.h"
Line 58 
Line 61 
 // //
 //     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 68 
Line 69 
 // //
 //============================================================================== //==============================================================================
  
 const Uint8 _to_upper_tbl[256] =  // Note: this table is much faster than the system toupper(). Please do not
   // change.
   
   const Uint8 _toUpperTable[256] =
 { {
     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
Line 104 
Line 108 
     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
 }; };
  
 const Uint8 _to_lower_tbl[256] =  // Note: this table is much faster than the system tulower(). Please do not
   // change.
   
   const Uint8 _toLowerTable[256] =
 { {
     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
Line 140 
Line 147 
     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
 }; };
  
 // Converts 16-bit characters to upper case.  // Converts 16-bit characters to upper case. This routine is faster than the
 inline Uint16 _to_upper(Uint16 x)  // system toupper(). Please do not change.
   inline Uint16 _toUpper(Uint16 x)
 { {
     return (x & 0xFF00) ? x : _to_upper_tbl[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 : _to_lower_tbl[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)
 { {
   #ifndef PEGASUS_STRING_NO_THROW
   
       // Check for potential overflow in x
       PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
   
   #endif
   
     if (x < 8)     if (x < 8)
         return 8;         return 8;
  
Line 172 
Line 188 
 template<class P, class Q> template<class P, class Q>
 static void _copy(P* p, const Q* q, size_t n) static void _copy(P* p, const Q* q, size_t n)
 { {
     // Use loop unrolling.      // The following employs loop unrolling for efficiency. Please do not
       // eliminate.
  
     while (n >= 8)     while (n >= 8)
     {     {
Line 206 
Line 223 
  
 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 262 
Line 282 
     return 0;     return 0;
 } }
  
 static int _compare_no_utf8(const Uint16* s1, const char* s2)  static int _compareNoUTF8(const Uint16* s1, const char* s2)
 { {
     Uint16 c1;     Uint16 c1;
     Uint16 c2;     Uint16 c2;
Line 280 
Line 300 
     return c1 - c2;     return c1 - c2;
 } }
  
 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)  
 { {
   #ifndef PEGASUS_STRING_NO_THROW
   
     if (!ptr)     if (!ptr)
         throw NullPointer();         throw NullPointer();
 }  
 #endif #endif
   }
   
   static void _StringThrowBadUTF8(Uint32 index)
   {
       MessageLoaderParms parms(
           "Common.String.BAD_UTF8",
           "The byte sequence starting at index $0 "
           "is not valid UTF-8 encoding.",
           index);
       throw Exception(parms);
   }
  
 static size_t _copy_from_utf8(Uint16* dest, const char* src, size_t n)  static size_t _copyFromUTF8(
       Uint16* dest,
       const char* src,
       size_t n,
       size_t& utf8_error_index)
 { {
     Uint16* p = dest;     Uint16* p = dest;
     const Uint8* q = (const Uint8*)src;     const Uint8* q = (const Uint8*)src;
Line 395 
Line 416 
             if (c > n || !isValid_U8(q, c) ||             if (c > n || !isValid_U8(q, c) ||
                 UTF8toUTF16(&q, q + c, &p, p + n) != 0)                 UTF8toUTF16(&q, q + c, &p, p + n) != 0)
             {             {
                 MessageLoaderParms parms("Common.String.BAD_UTF8",                  utf8_error_index = q - (const Uint8*)src;
                     "The byte sequence starting at index $0 "                  return size_t(-1);
                     "is not valid UTF-8 encoding.",  
                      q - (const Uint8*)src);  
                 throw Exception(parms);  
             }             }
  
             n -= c;             n -= c;
Line 411 
Line 429 
  
 // 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 464 
Line 485 
     return p - (Uint8*)dest;     return p - (Uint8*)dest;
 } }
  
 static inline size_t _convert(Uint16* p, const char* q, size_t n)  static inline size_t _convert(
       Uint16* p, const char* q, size_t n, size_t& utf8_error_index)
 { {
 #ifdef PEGASUS_STRING_NO_UTF8 #ifdef PEGASUS_STRING_NO_UTF8
     _copy(p, q, n);     _copy(p, q, n);
     return n;     return n;
 #else #else
     return _copy_from_utf8(p, q, n);      return _copyFromUTF8(p, q, n, utf8_error_index);
 #endif #endif
 } }
  
Line 517 
Line 539 
 // //
 //============================================================================== //==============================================================================
  
 StringRep StringRep::_empty_rep;  StringRep StringRep::_emptyRep;
  
 inline StringRep* StringRep::alloc(size_t cap) inline StringRep* StringRep::alloc(size_t cap)
 { {
   #ifndef PEGASUS_STRING_NO_THROW
   
       // Check for potential overflow in cap
       PEGASUS_CHECK_CAPACITY_OVERFLOW(cap);
   
   #endif
   
     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 551 
Line 580 
     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;  #ifndef PEGASUS_STRING_NO_THROW
       if (rep->size == size_t(-1))
       {
           StringRep::free(rep);
           _StringThrowBadUTF8(utf8_error_index);
 } }
   #endif
   
       rep->data[rep->size] = '\0';
  
 StringRep* StringRep::createASCII7(const char* data, size_t size)  
 {  
     StringRep* rep = StringRep::alloc(size);  
     _copy((Uint16*)rep->data, data, size);  
     rep->data[rep->size = size] = '\0';  
     return rep;     return rep;
 } }
  
Line 602 
Line 633 
  
 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 656 
Line 681 
  
 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);
   
   #ifndef PEGASUS_STRING_NO_THROW
       if (tmp == size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8(utf8_error_index);
       }
   #endif
   
       _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);
   
   #ifndef PEGASUS_STRING_NO_THROW
       if (tmp ==  size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8(utf8_error_index);
       }
   #endif
   
       _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 689 
Line 738 
  
 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 706 
Line 755 
  
 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;  #ifndef PEGASUS_STRING_NO_THROW
 }      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(utf8_error_index);
     }     }
   #endif
  
     _copy(_rep->data, str, n);      _rep->data[_rep->size] = 0;
     _rep->data[_rep->size = n] = 0;  
  
     return *this;     return *this;
 } }
Line 740 
Line 784 
 { {
     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 757 
Line 804 
  
 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);
Line 765 
Line 820 
 #else #else
     Uint32 n = 3 * _rep->size;     Uint32 n = 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 773 
Line 828 
  
 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, 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])), 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, 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);
   
   #ifndef PEGASUS_STRING_NO_THROW
       if (tmp ==  size_t(-1))
       {
           StringRep::free(_rep);
           _rep = &StringRep::_emptyRep;
           _StringThrowBadUTF8(utf8_error_index);
       }
   #endif
   
       _rep->size += tmp;
     _rep->data[_rep->size] = '\0';     _rep->data[_rep->size] = '\0';
  
     return *this;     return *this;
Line 809 
Line 877 
     if (n == PEG_NOT_FOUND)     if (n == PEG_NOT_FOUND)
         n = _rep->size - index;         n = _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 836 
Line 904 
         if (n == PEG_NOT_FOUND || n > _rep->size - index)         if (n == PEG_NOT_FOUND || n > _rep->size - index)
             n = _rep->size - index;             n = _rep->size - index;
  
         return String((Char16*)_rep->data + index, n);          return String((Char16*)(_rep->data + index), n);
     }     }
  
     return String();     return String();
Line 847 
Line 915 
     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 862 
Line 930 
     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 882 
Line 951 
             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 894 
Line 963 
  
 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 910 
Line 979 
     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 922 
Line 991 
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
         if (Atomic_get(&_rep->refs) != 1)          if (_rep->refs.get() != 1)
                 _rep = StringRep::copy_on_write(_rep);              _rep = StringRep::copyOnWrite(_rep);
  
         // This will do a locale-insensitive, but context-sensitive convert.         // This will do a locale-insensitive, but context-sensitive convert.
         // Since context-sensitive casing looks at adjacent chars, this         // Since context-sensitive casing looks at adjacent chars, this
Line 936 
Line 1005 
  
         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;         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;         return;
     }     }
  
 #endif /* PEGASUS_HAS_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 966 
Line 1035 
     for (; n--; p++)     for (; n--; p++)
     {     {
         if (!(*p & 0xFF00))         if (!(*p & 0xFF00))
             *p = _to_lower(*p);              *p = _toLower(*p);
     }     }
 } }
  
Line 976 
Line 1045 
  
     if (InitializeICU::initICUSuccessful())     if (InitializeICU::initICUSuccessful())
     {     {
         if (Atomic_get(&_rep->refs) != 1)          if (_rep->refs.get() != 1)
             _rep = StringRep::copy_on_write(_rep);              _rep = StringRep::copyOnWrite(_rep);
  
         // This will do a locale-insensitive, but context-sensitive convert.         // This will do a locale-insensitive, but context-sensitive convert.
         // Since context-sensitive casing looks at adjacent chars, this         // Since context-sensitive casing looks at adjacent chars, this
Line 990 
Line 1059 
  
         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;         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;         return;
     }     }
  
 #endif /* PEGASUS_HAS_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 1038 
Line 1119 
  
 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 1065 
Line 1146 
  
     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 1079 
Line 1160 
     return 0;     return 0;
 } }
  
 Boolean String::equalNoCase_aux(const String& s1, const String& s2)  Boolean StringEqualNoCase(const String& s1, const String& s2)
 { {
 #ifdef PEGASUS_HAS_ICU #ifdef PEGASUS_HAS_ICU
  
Line 1087 
Line 1168 
  
 #else /* PEGASUS_HAS_ICU */ #else /* PEGASUS_HAS_ICU */
  
     Uint16* p = (Uint16*)s1._rep->data;      // The following employs loop unrolling for efficiency. Please do not
     Uint16* q = (Uint16*)s2._rep->data;      // eliminate.
     Uint32 n = s2._rep->size;  
       Uint16* p = (Uint16*)s1.getChar16Data();
       Uint16* q = (Uint16*)s2.getChar16Data();
       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 1112 
Line 1196 
  
     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 1127 
Line 1211 
  
     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 1141 
Line 1225 
  
 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_HAS_ICU) #if defined(PEGASUS_HAS_ICU)
  
Line 1158 
Line 1242 
         if (!*p2)         if (!*p2)
             return false;             return false;
  
         if (_to_upper(*p1++) != _to_upper_tbl[int(*p2++)])          if (_toUpper(*p1++) != _toUpperTable[int(*p2++)])
             return false;             return false;
     }     }
  
Line 1185 
Line 1269 
 { {
 #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 1253 
Line 1337 
 #endif // PEGASUS_OS_OS400 #endif // PEGASUS_OS_OS400
 } }
  
 void String::_append_char_aux()  void StringAppendCharAux(StringRep*& _rep)
 { {
     StringRep* tmp;     StringRep* tmp;
  
Line 1296 
Line 1380 
         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 1306 
Line 1390 
                 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 1345 
Line 1429 
             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 1400 
Line 1484 
  
         This avoids slower UTF8 processing when not needed.         This avoids slower UTF8 processing when not needed.
  
 BUG-4200 Review notes:  ================================================================================
   
   TO-DO:
   
       (+) [DONE] Use PEGASUS_USE_EXPERIMENTAL_INTERFACES
   
       (+) [DONE] Submit BUG-2754 (Windows buffer limit).
   
       (+) [DONE] Eliminate char versions of find() and append().
   
       (+) [DONE] Remove PEGASUS_MAX_PRINTABLE_CHARACTER from Config.h
   
       (+) [DONE] Change _next_pow_2() to _roundUpToPow2().
   
       (+) [DONE] Change '99' to '2' in StringRep constructor (comment as well).
   
       (+) [DONE] Comment StringRep allocation layout.
   
       (+) [DONE] Conceal private inline functions.
  
     1.  Use PEGASUS_USE_EXPERIMENTAL_INTERFACES instead of      (+) [DONE] Shorten inclusion of StringInline.h in String.h.
         PEGASUS_STRING_EXTENSIONS.  
  
         Status: done      (+) [DONE] Change USE_INTERNAL_INLINE TO DISABLE_INTERNAL_INLINE or get
           rid of altogether.
  
     2.  Doc++ String.h      (+) [DONE] useCamelNotationOnAllFunctionNames.
  
         Status: pending      (+) [DONE] Check for overlow condition in StringRep::alloc().
  
     3.  Look at PEP223 for security coding guidelines for strings.      (+) [DONE] Remove tabs (used vim ":set expandtab" and ":retab").
  
         Status: pending      (+) [DONE] Fix throw-related memory leak.
  
     4.  Increasing the number of objects may break Windows 2000 build      (+) [DONE] Look at PEP223 for coding security guidelines.
         (limit of 2048 bytes for command line). See BUG-2754  
  
         Status: submitted patch for bug 2754      (+) [DONE] Use old AtomicInt for now (new AtomicInt part of bug #4250).
  
     5.  Concerns about whether generating inlines and non-inline versions      (+) [DONE] Removed appendASCII() and the ASCII form of the constructor.
         of functions will work with all compilers.  
  
         Status: tested on Windows. Also showed how inlining can be disabled      (+) DOC++ String.h - will open new bug?
         on platforms that don't support it.  
  
     6.  Atomic.h -- more to come      (+) Added PEGASUS_DISABLE_INTERNAL_INLINES macro (to permit suppression
           on certain platforms).
  
 ================================================================================ ================================================================================
 */ */


Legend:
Removed from v.1.111.6.3  
changed lines
  Added in v.1.119.2.2

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2