Ignore:
Timestamp:
Jul 6, 2008, 7:49:29 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-07-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Second step in broad cleanup effort.

[ File list elided ]

WebCore:

2008-07-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Add #include for kjs/protect.h.

  • xml/XMLHttpRequest.cpp: (WebCore::XMLHttpRequest::loadRequestAsynchronously):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r35016 r35027  
    1 // -*- c-basic-offset: 2 -*-
    21/*
    32 *  Copyright (C) 1999-2000 Harri Porten ([email protected])
     
    7978COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes)
    8079
    81 CString::CString(const char *c)
    82 {
    83   length = strlen(c);
    84   data = new char[length+1];
    85   memcpy(data, c, length + 1);
    86 }
    87 
    88 CString::CString(const char *c, size_t len)
    89 {
    90   length = len;
    91   data = new char[len+1];
    92   memcpy(data, c, len);
    93   data[len] = 0;
    94 }
    95 
    96 CString::CString(const CString &b)
    97 {
    98   length = b.length;
    99   if (b.data) {
    100     data = new char[length+1];
    101     memcpy(data, b.data, length + 1);
    102   }
    103   else
    104     data = 0;
     80CString::CString(const char* c)
     81    : m_length(strlen(c))
     82    , m_data(new char[m_length + 1])
     83{
     84    memcpy(m_data, c, m_length + 1);
     85}
     86
     87CString::CString(const char* c, size_t length)
     88    : m_length(length)
     89    , m_data(new char[length + 1])
     90{
     91    memcpy(m_data, c, m_length);
     92    m_data[m_length] = 0;
     93}
     94
     95CString::CString(const CString& b)
     96{
     97    m_length = b.m_length;
     98    if (b.m_data) {
     99        m_data = new char[m_length + 1];
     100        memcpy(m_data, b.m_data, m_length + 1);
     101    } else
     102        m_data = 0;
    105103}
    106104
    107105CString::~CString()
    108106{
    109   delete [] data;
    110 }
    111 
    112 CString CString::adopt(char* c, size_t len)
     107    delete [] m_data;
     108}
     109
     110CString CString::adopt(char* c, size_t length)
    113111{
    114112    CString s;
    115     s.data = c;
    116     s.length = len;
    117    
     113    s.m_data = c;
     114    s.m_length = length;
    118115    return s;
    119116}
    120117
    121 CString &CString::append(const CString &t)
    122 {
    123   char *n;
    124   n = new char[length+t.length+1];
    125   if (length)
    126     memcpy(n, data, length);
    127   if (t.length)
    128     memcpy(n+length, t.data, t.length);
    129   length += t.length;
    130   n[length] = 0;
    131 
    132   delete [] data;
    133   data = n;
    134 
    135   return *this;
    136 }
    137 
    138 CString &CString::operator=(const char *c)
    139 {
    140   if (data)
    141     delete [] data;
    142   length = strlen(c);
    143   data = new char[length+1];
    144   memcpy(data, c, length + 1);
    145 
    146   return *this;
    147 }
    148 
    149 CString &CString::operator=(const CString &str)
    150 {
    151   if (this == &str)
     118CString& CString::append(const CString& t)
     119{
     120    char* n;
     121    n = new char[m_length + t.m_length + 1];
     122    if (m_length)
     123        memcpy(n, m_data, m_length);
     124    if (t.m_length)
     125        memcpy(n + m_length, t.m_data, t.m_length);
     126    m_length += t.m_length;
     127    n[m_length] = 0;
     128
     129    delete [] m_data;
     130    m_data = n;
     131
    152132    return *this;
    153 
    154   if (data)
    155     delete [] data;
    156   length = str.length;
    157   if (str.data) {
    158     data = new char[length + 1];
    159     memcpy(data, str.data, length + 1);
    160   }
    161   else
    162     data = 0;
    163 
    164   return *this;
     133}
     134
     135CString& CString::operator=(const char* c)
     136{
     137    if (m_data)
     138        delete [] m_data;
     139    m_length = strlen(c);
     140    m_data = new char[m_length + 1];
     141    memcpy(m_data, c, m_length + 1);
     142
     143    return *this;
     144}
     145
     146CString& CString::operator=(const CString& str)
     147{
     148    if (this == &str)
     149        return *this;
     150
     151    if (m_data)
     152        delete [] m_data;
     153    m_length = str.m_length;
     154    if (str.m_data) {
     155        m_data = new char[m_length + 1];
     156        memcpy(m_data, str.m_data, m_length + 1);
     157    } else
     158        m_data = 0;
     159
     160    return *this;
    165161}
    166162
    167163bool operator==(const CString& c1, const CString& c2)
    168164{
    169   size_t len = c1.size();
    170   return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
    171 }
    172 
    173 // These static strings are immutable, except for rc, whose initial value is chosen to reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
     165    size_t len = c1.size();
     166    return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
     167}
     168
     169// These static strings are immutable, except for rc, whose initial value is chosen to
     170// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
    174171static UChar sharedEmptyChar;
    175172UString::Rep UString::Rep::null = { 0, 0, INT_MAX / 2, 0, 0, &UString::Rep::null, true, 0, 0, 0, 0, 0, 0 };
     
    178175static char* statBuffer = 0; // Only used for debugging via UString::ascii().
    179176
    180 PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar *d, int l)
    181 {
    182   int sizeInBytes = l * sizeof(UChar);
    183   UChar *copyD = static_cast<UChar *>(fastMalloc(sizeInBytes));
    184   memcpy(copyD, d, sizeInBytes);
    185 
    186   return create(copyD, l);
    187 }
    188 
    189 PassRefPtr<UString::Rep> UString::Rep::create(UChar *d, int l)
    190 {
    191   Rep* r = new Rep;
    192   r->offset = 0;
    193   r->len = l;
    194   r->rc = 1;
    195   r->_hash = 0;
    196   r->identifierTable = 0;
    197   r->baseString = r;
    198   r->isStatic = false;
    199   r->reportedCost = 0;
    200   r->buf = d;
    201   r->usedCapacity = l;
    202   r->capacity = l;
    203   r->usedPreCapacity = 0;
    204   r->preCapacity = 0;
    205 
    206   // steal the single reference this Rep was created with
    207   return adoptRef(r);
     177PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l)
     178{
     179    int sizeInBytes = l * sizeof(UChar);
     180    UChar* copyD = static_cast<UChar*>(fastMalloc(sizeInBytes));
     181    memcpy(copyD, d, sizeInBytes);
     182
     183    return create(copyD, l);
     184}
     185
     186PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l)
     187{
     188    Rep* r = new Rep;
     189    r->offset = 0;
     190    r->len = l;
     191    r->rc = 1;
     192    r->_hash = 0;
     193    r->identifierTable = 0;
     194    r->baseString = r;
     195    r->isStatic = false;
     196    r->reportedCost = 0;
     197    r->buf = d;
     198    r->usedCapacity = l;
     199    r->capacity = l;
     200    r->usedPreCapacity = 0;
     201    r->preCapacity = 0;
     202
     203    // steal the single reference this Rep was created with
     204    return adoptRef(r);
    208205}
    209206
    210207PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
    211208{
    212   ASSERT(base);
    213 
    214   int baseOffset = base->offset;
    215 
    216   base = base->baseString;
    217 
    218   ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
    219   ASSERT(offset + baseOffset + length <= base->usedCapacity);
    220 
    221   Rep *r = new Rep;
    222   r->offset = baseOffset + offset;
    223   r->len = length;
    224   r->rc = 1;
    225   r->_hash = 0;
    226   r->identifierTable = 0;
    227   r->baseString = base.releaseRef();
    228   r->isStatic = false;
    229   r->reportedCost = 0;
    230   r->buf = 0;
    231   r->usedCapacity = 0;
    232   r->capacity = 0;
    233   r->usedPreCapacity = 0;
    234   r->preCapacity = 0;
    235 
    236   // steal the single reference this Rep was created with
    237   return adoptRef(r);
     209    ASSERT(base);
     210
     211    int baseOffset = base->offset;
     212
     213    base = base->baseString;
     214
     215    ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
     216    ASSERT(offset + baseOffset + length <= base->usedCapacity);
     217
     218    Rep* r = new Rep;
     219    r->offset = baseOffset + offset;
     220    r->len = length;
     221    r->rc = 1;
     222    r->_hash = 0;
     223    r->identifierTable = 0;
     224    r->baseString = base.releaseRef();
     225    r->isStatic = false;
     226    r->reportedCost = 0;
     227    r->buf = 0;
     228    r->usedCapacity = 0;
     229    r->capacity = 0;
     230    r->usedPreCapacity = 0;
     231    r->preCapacity = 0;
     232
     233    // steal the single reference this Rep was created with
     234    return adoptRef(r);
    238235}
    239236
     
    254251void UString::Rep::destroy()
    255252{
    256   // Static null and empty strings can never be destroyed, but we cannot rely on reference counting, because ref/deref are not thread-safe.
    257   if (!isStatic) {
    258     if (identifierTable)
    259       Identifier::remove(this);
    260     if (baseString == this)
    261       fastFree(buf);
    262     else
    263       baseString->deref();
    264 
    265     delete this;
    266   }
     253    // Static null and empty strings can never be destroyed, but we cannot rely on
     254    // reference counting, because ref/deref are not thread-safe.
     255    if (!isStatic) {
     256        if (identifierTable)
     257            Identifier::remove(this);
     258        if (baseString == this)
     259            fastFree(buf);
     260        else
     261            baseString->deref();
     262
     263        delete this;
     264    }
    267265}
    268266
     
    273271// Paul Hsieh's SuperFastHash
    274272// http://www.azillionmonkeys.com/qed/hash.html
    275 unsigned UString::Rep::computeHash(const UChar *s, int len)
    276 {
    277   unsigned l = len;
    278   uint32_t hash = PHI;
    279   uint32_t tmp;
    280 
    281   int rem = l & 1;
    282   l >>= 1;
    283 
    284   // Main loop
    285   for (; l > 0; l--) {
    286     hash += s[0];
    287     tmp = (s[1] << 11) ^ hash;
    288     hash = (hash << 16) ^ tmp;
    289     s += 2;
    290     hash += hash >> 11;
    291   }
    292 
    293   // Handle end case
    294   if (rem) {
    295     hash += s[0];
    296     hash ^= hash << 11;
    297     hash += hash >> 17;
    298   }
    299 
    300   // Force "avalanching" of final 127 bits
    301   hash ^= hash << 3;
    302   hash += hash >> 5;
    303   hash ^= hash << 2;
    304   hash += hash >> 15;
    305   hash ^= hash << 10;
    306 
    307   // this avoids ever returning a hash code of 0, since that is used to
    308   // signal "hash not computed yet", using a value that is likely to be
    309   // effectively the same as 0 when the low bits are masked
    310   if (hash == 0)
    311     hash = 0x80000000;
    312 
    313   return hash;
     273unsigned UString::Rep::computeHash(const UChar* s, int len)
     274{
     275    unsigned l = len;
     276    uint32_t hash = PHI;
     277    uint32_t tmp;
     278
     279    int rem = l & 1;
     280    l >>= 1;
     281
     282    // Main loop
     283    for (; l > 0; l--) {
     284        hash += s[0];
     285        tmp = (s[1] << 11) ^ hash;
     286        hash = (hash << 16) ^ tmp;
     287        s += 2;
     288        hash += hash >> 11;
     289    }
     290
     291    // Handle end case
     292    if (rem) {
     293        hash += s[0];
     294        hash ^= hash << 11;
     295        hash += hash >> 17;
     296    }
     297
     298    // Force "avalanching" of final 127 bits
     299    hash ^= hash << 3;
     300    hash += hash >> 5;
     301    hash ^= hash << 2;
     302    hash += hash >> 15;
     303    hash ^= hash << 10;
     304
     305    // this avoids ever returning a hash code of 0, since that is used to
     306    // signal "hash not computed yet", using a value that is likely to be
     307    // effectively the same as 0 when the low bits are masked
     308    if (hash == 0)
     309        hash = 0x80000000;
     310
     311    return hash;
    314312}
    315313
    316314// Paul Hsieh's SuperFastHash
    317315// http://www.azillionmonkeys.com/qed/hash.html
    318 unsigned UString::Rep::computeHash(const char *s)
    319 {
    320   // This hash is designed to work on 16-bit chunks at a time. But since the normal case
    321   // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
    322   // were 16-bit chunks, which should give matching results
    323 
    324   uint32_t hash = PHI;
    325   uint32_t tmp;
    326   size_t l = strlen(s);
    327  
    328   size_t rem = l & 1;
    329   l >>= 1;
    330 
    331   // Main loop
    332   for (; l > 0; l--) {
    333     hash += (unsigned char)s[0];
    334     tmp = ((unsigned char)s[1] << 11) ^ hash;
    335     hash = (hash << 16) ^ tmp;
    336     s += 2;
    337     hash += hash >> 11;
    338   }
    339 
    340   // Handle end case
    341   if (rem) {
    342     hash += (unsigned char)s[0];
    343     hash ^= hash << 11;
    344     hash += hash >> 17;
    345   }
    346 
    347   // Force "avalanching" of final 127 bits
    348   hash ^= hash << 3;
    349   hash += hash >> 5;
    350   hash ^= hash << 2;
    351   hash += hash >> 15;
    352   hash ^= hash << 10;
    353  
    354   // this avoids ever returning a hash code of 0, since that is used to
    355   // signal "hash not computed yet", using a value that is likely to be
    356   // effectively the same as 0 when the low bits are masked
    357   if (hash == 0)
    358     hash = 0x80000000;
    359 
    360   return hash;
     316unsigned UString::Rep::computeHash(const char* s)
     317{
     318    // This hash is designed to work on 16-bit chunks at a time. But since the normal case
     319    // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
     320    // were 16-bit chunks, which should give matching results
     321
     322    uint32_t hash = PHI;
     323    uint32_t tmp;
     324    size_t l = strlen(s);
     325
     326    size_t rem = l & 1;
     327    l >>= 1;
     328
     329    // Main loop
     330    for (; l > 0; l--) {
     331        hash += static_cast<unsigned char>(s[0]);
     332        tmp = (static_cast<unsigned char>(s[1]) << 11) ^ hash;
     333        hash = (hash << 16) ^ tmp;
     334        s += 2;
     335        hash += hash >> 11;
     336    }
     337
     338    // Handle end case
     339    if (rem) {
     340        hash += static_cast<unsigned char>(s[0]);
     341        hash ^= hash << 11;
     342        hash += hash >> 17;
     343    }
     344
     345    // Force "avalanching" of final 127 bits
     346    hash ^= hash << 3;
     347    hash += hash >> 5;
     348    hash ^= hash << 2;
     349    hash += hash >> 15;
     350    hash ^= hash << 10;
     351
     352    // this avoids ever returning a hash code of 0, since that is used to
     353    // signal "hash not computed yet", using a value that is likely to be
     354    // effectively the same as 0 when the low bits are masked
     355    if (hash == 0)
     356        hash = 0x80000000;
     357
     358    return hash;
    361359}
    362360
     
    379377inline int UString::usedCapacity() const
    380378{
    381   return m_rep->baseString->usedCapacity;
     379    return m_rep->baseString->usedCapacity;
    382380}
    383381
    384382inline int UString::usedPreCapacity() const
    385383{
    386   return m_rep->baseString->usedPreCapacity;
     384    return m_rep->baseString->usedPreCapacity;
    387385}
    388386
    389387void UString::expandCapacity(int requiredLength)
    390388{
    391   Rep* r = m_rep->baseString;
    392 
    393   if (requiredLength > r->capacity) {
    394     size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
    395     UChar* oldBuf = r->buf;
    396     r->buf = reallocChars(r->buf, newCapacity);
    397     if (!r->buf) {
    398         r->buf = oldBuf;
     389    Rep* r = m_rep->baseString;
     390
     391    if (requiredLength > r->capacity) {
     392        size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
     393        UChar* oldBuf = r->buf;
     394        r->buf = reallocChars(r->buf, newCapacity);
     395        if (!r->buf) {
     396            r->buf = oldBuf;
     397            m_rep = &Rep::null;
     398            return;
     399        }
     400        r->capacity = newCapacity - r->preCapacity;
     401    }
     402    if (requiredLength > r->usedCapacity)
     403        r->usedCapacity = requiredLength;
     404}
     405
     406void UString::expandPreCapacity(int requiredPreCap)
     407{
     408    Rep* r = m_rep->baseString;
     409
     410    if (requiredPreCap > r->preCapacity) {
     411        size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
     412        int delta = newCapacity - r->capacity - r->preCapacity;
     413
     414        UChar* newBuf = allocChars(newCapacity);
     415        if (!newBuf) {
     416            m_rep = &Rep::null;
     417            return;
     418        }
     419        memcpy(newBuf + delta, r->buf, (r->capacity + r->preCapacity) * sizeof(UChar));
     420        fastFree(r->buf);
     421        r->buf = newBuf;
     422
     423        r->preCapacity = newCapacity - r->capacity;
     424    }
     425    if (requiredPreCap > r->usedPreCapacity)
     426        r->usedPreCapacity = requiredPreCap;
     427}
     428
     429UString::UString(const char* c)
     430{
     431    if (!c) {
    399432        m_rep = &Rep::null;
    400433        return;
    401434    }
    402     r->capacity = newCapacity - r->preCapacity;
    403   }
    404   if (requiredLength > r->usedCapacity) {
    405     r->usedCapacity = requiredLength;
    406   }
    407 }
    408 
    409 void UString::expandPreCapacity(int requiredPreCap)
    410 {
    411   Rep* r = m_rep->baseString;
    412 
    413   if (requiredPreCap > r->preCapacity) {
    414     size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
    415     int delta = newCapacity - r->capacity - r->preCapacity;
    416 
    417     UChar* newBuf = allocChars(newCapacity);
    418     if (!newBuf) {
     435
     436    if (!c[0]) {
     437        m_rep = &Rep::empty;
     438        return;
     439    }
     440
     441    size_t length = strlen(c);
     442    UChar* d = allocChars(length);
     443    if (!d)
    419444        m_rep = &Rep::null;
    420         return;
    421     }
    422     memcpy(newBuf + delta, r->buf, (r->capacity + r->preCapacity) * sizeof(UChar));
    423     fastFree(r->buf);
    424     r->buf = newBuf;
    425 
    426     r->preCapacity = newCapacity - r->capacity;
    427   }
    428   if (requiredPreCap > r->usedPreCapacity) {
    429     r->usedPreCapacity = requiredPreCap;
    430   }
    431 }
    432 
    433 UString::UString(const char *c)
    434 {
    435   if (!c) {
    436     m_rep = &Rep::null;
    437     return;
    438   }
    439 
    440   if (!c[0]) {
    441     m_rep = &Rep::empty;
    442     return;
    443   }
    444 
    445   size_t length = strlen(c);
    446   UChar *d = allocChars(length);
    447   if (!d)
    448       m_rep = &Rep::null;
    449   else {
    450       for (size_t i = 0; i < length; i++)
    451           d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
    452       m_rep = Rep::create(d, static_cast<int>(length));
    453   }
    454 }
    455 
    456 UString::UString(const UChar *c, int length)
    457 {
    458   if (length == 0)
    459     m_rep = &Rep::empty;
    460   else
    461     m_rep = Rep::createCopying(c, length);
    462 }
    463 
    464 UString::UString(UChar *c, int length, bool copy)
    465 {
    466   if (length == 0)
    467     m_rep = &Rep::empty;
    468   else if (copy)
    469     m_rep = Rep::createCopying(c, length);
    470   else
    471     m_rep = Rep::create(c, length);
     445    else {
     446        for (size_t i = 0; i < length; i++)
     447            d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
     448        m_rep = Rep::create(d, static_cast<int>(length));
     449    }
     450}
     451
     452UString::UString(const UChar* c, int length)
     453{
     454    if (length == 0)
     455        m_rep = &Rep::empty;
     456    else
     457        m_rep = Rep::createCopying(c, length);
     458}
     459
     460UString::UString(UChar* c, int length, bool copy)
     461{
     462    if (length == 0)
     463        m_rep = &Rep::empty;
     464    else if (copy)
     465        m_rep = Rep::createCopying(c, length);
     466    else
     467        m_rep = Rep::create(c, length);
    472468}
    473469
     
    481477
    482478
    483 UString::UString(const UString &a, const UString &b)
    484 {
    485   int aSize = a.size();
    486   int aOffset = a.m_rep->offset;
    487   int bSize = b.size();
    488   int bOffset = b.m_rep->offset;
    489   int length = aSize + bSize;
    490 
    491   // possible cases:
    492  
    493   if (aSize == 0) {
    494     // a is empty
    495     m_rep = b.m_rep;
    496   } else if (bSize == 0) {
    497     // b is empty
    498     m_rep = a.m_rep;
    499   } else if (aOffset + aSize == a.usedCapacity() && aSize >= minShareSize && 4 * aSize >= bSize &&
    500              (-bOffset != b.usedPreCapacity() || aSize >= bSize)) {
    501     // - a reaches the end of its buffer so it qualifies for shared append
    502     // - also, it's at least a quarter the length of b - appending to a much shorter
    503     //   string does more harm than good
    504     // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
    505     UString x(a);
    506     x.expandCapacity(aOffset + length);
    507     if (a.data() && x.data()) {
    508         memcpy(const_cast<UChar *>(a.data() + aSize), b.data(), bSize * sizeof(UChar));
    509         m_rep = Rep::create(a.m_rep, 0, length);
    510     } else
    511         m_rep = &Rep::null;
    512   } else if (-bOffset == b.usedPreCapacity() && bSize >= minShareSize  && 4 * bSize >= aSize) {
    513     // - b reaches the beginning of its buffer so it qualifies for shared prepend
    514     // - also, it's at least a quarter the length of a - prepending to a much shorter
    515     //   string does more harm than good
    516     UString y(b);
    517     y.expandPreCapacity(-bOffset + aSize);
    518     if (b.data() && y.data()) {
    519         memcpy(const_cast<UChar *>(b.data() - aSize), a.data(), aSize * sizeof(UChar));
    520         m_rep = Rep::create(b.m_rep, -aSize, length);
    521     } else
    522         m_rep = &Rep::null;
    523   } else {
    524     // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
    525     size_t newCapacity = expandedSize(length, 0);
    526     UChar* d = allocChars(newCapacity);
    527     if (!d)
    528         m_rep = &Rep::null;
     479UString::UString(const UString& a, const UString& b)
     480{
     481    int aSize = a.size();
     482    int aOffset = a.m_rep->offset;
     483    int bSize = b.size();
     484    int bOffset = b.m_rep->offset;
     485    int length = aSize + bSize;
     486
     487    // possible cases:
     488
     489    if (aSize == 0) {
     490        // a is empty
     491        m_rep = b.m_rep;
     492    } else if (bSize == 0) {
     493        // b is empty
     494        m_rep = a.m_rep;
     495    } else if (aOffset + aSize == a.usedCapacity() && aSize >= minShareSize && 4 * aSize >= bSize &&
     496               (-bOffset != b.usedPreCapacity() || aSize >= bSize)) {
     497        // - a reaches the end of its buffer so it qualifies for shared append
     498        // - also, it's at least a quarter the length of b - appending to a much shorter
     499        //   string does more harm than good
     500        // - however, if b qualifies for prepend and is longer than a, we'd rather prepend
     501        UString x(a);
     502        x.expandCapacity(aOffset + length);
     503        if (a.data() && x.data()) {
     504            memcpy(const_cast<UChar*>(a.data() + aSize), b.data(), bSize * sizeof(UChar));
     505            m_rep = Rep::create(a.m_rep, 0, length);
     506        } else
     507            m_rep = &Rep::null;
     508    } else if (-bOffset == b.usedPreCapacity() && bSize >= minShareSize  && 4 * bSize >= aSize) {
     509        // - b reaches the beginning of its buffer so it qualifies for shared prepend
     510        // - also, it's at least a quarter the length of a - prepending to a much shorter
     511        //   string does more harm than good
     512        UString y(b);
     513        y.expandPreCapacity(-bOffset + aSize);
     514        if (b.data() && y.data()) {
     515            memcpy(const_cast<UChar *>(b.data() - aSize), a.data(), aSize * sizeof(UChar));
     516            m_rep = Rep::create(b.m_rep, -aSize, length);
     517        } else
     518            m_rep = &Rep::null;
     519    } else {
     520        // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
     521        size_t newCapacity = expandedSize(length, 0);
     522        UChar* d = allocChars(newCapacity);
     523        if (!d)
     524            m_rep = &Rep::null;
     525        else {
     526            memcpy(d, a.data(), aSize * sizeof(UChar));
     527            memcpy(d + aSize, b.data(), bSize * sizeof(UChar));
     528            m_rep = Rep::create(d, length);
     529            m_rep->capacity = newCapacity;
     530        }
     531    }
     532}
     533
     534const UString& UString::null()
     535{
     536    static UString* n = new UString; // Should be called from main thread at least once to be safely initialized.
     537    return *n;
     538}
     539
     540UString UString::from(int i)
     541{
     542    UChar buf[1 + sizeof(i) * 3];
     543    UChar* end = buf + sizeof(buf) / sizeof(UChar);
     544    UChar* p = end;
     545 
     546    if (i == 0)
     547        *--p = '0';
     548    else if (i == INT_MIN) {
     549        char minBuf[1 + sizeof(i) * 3];
     550        sprintf(minBuf, "%d", INT_MIN);
     551        return UString(minBuf);
     552    } else {
     553        bool negative = false;
     554        if (i < 0) {
     555            negative = true;
     556            i = -i;
     557        }
     558        while (i) {
     559            *--p = static_cast<unsigned short>((i % 10) + '0');
     560            i /= 10;
     561        }
     562        if (negative)
     563            *--p = '-';
     564    }
     565
     566    return UString(p, static_cast<int>(end - p));
     567}
     568
     569UString UString::from(unsigned int u)
     570{
     571    UChar buf[sizeof(u) * 3];
     572    UChar* end = buf + sizeof(buf) / sizeof(UChar);
     573    UChar* p = end;
     574   
     575    if (u == 0)
     576        *--p = '0';
    529577    else {
    530         memcpy(d, a.data(), aSize * sizeof(UChar));
    531         memcpy(d + aSize, b.data(), bSize * sizeof(UChar));
    532         m_rep = Rep::create(d, length);
    533         m_rep->capacity = newCapacity;
    534     }
    535   }
    536 }
    537 
    538 const UString& UString::null()
    539 {
    540   static UString* n = new UString; // Should be called from main thread at least once to be safely initialized.
    541   return *n;
    542 }
    543 
    544 UString UString::from(int i)
    545 {
    546   UChar buf[1 + sizeof(i) * 3];
    547   UChar *end = buf + sizeof(buf) / sizeof(UChar);
    548   UChar *p = end;
     578        while (u) {
     579            *--p = static_cast<unsigned short>((u % 10) + '0');
     580            u /= 10;
     581        }
     582    }
     583   
     584    return UString(p, static_cast<int>(end - p));
     585}
     586
     587UString UString::from(long l)
     588{
     589    UChar buf[1 + sizeof(l) * 3];
     590    UChar* end = buf + sizeof(buf) / sizeof(UChar);
     591    UChar* p = end;
     592
     593    if (l == 0)
     594        *--p = '0';
     595    else if (l == LONG_MIN) {
     596        char minBuf[1 + sizeof(l) * 3];
     597        sprintf(minBuf, "%ld", LONG_MIN);
     598        return UString(minBuf);
     599    } else {
     600        bool negative = false;
     601        if (l < 0) {
     602            negative = true;
     603            l = -l;
     604        }
     605        while (l) {
     606            *--p = static_cast<unsigned short>((l % 10) + '0');
     607            l /= 10;
     608        }
     609        if (negative)
     610            *--p = '-';
     611    }
     612
     613    return UString(p, static_cast<int>(end - p));
     614}
     615
     616UString UString::from(double d)
     617{
     618    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
     619    if (isnan(d))
     620        return "NaN";
     621
     622    char buf[80];
     623    int decimalPoint;
     624    int sign;
     625
     626    char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
     627    int length = static_cast<int>(strlen(result));
    549628 
    550   if (i == 0) {
    551     *--p = '0';
    552   } else if (i == INT_MIN) {
    553     char minBuf[1 + sizeof(i) * 3];
    554     sprintf(minBuf, "%d", INT_MIN);
    555     return UString(minBuf);
    556   } else {
    557     bool negative = false;
    558     if (i < 0) {
    559       negative = true;
    560       i = -i;
    561     }
    562     while (i) {
    563       *--p = (unsigned short)((i % 10) + '0');
    564       i /= 10;
    565     }
    566     if (negative) {
    567       *--p = '-';
    568     }
    569   }
     629    int i = 0;
     630    if (sign)
     631        buf[i++] = '-';
    570632 
    571   return UString(p, static_cast<int>(end - p));
    572 }
    573 
    574 UString UString::from(unsigned int u)
    575 {
    576   UChar buf[sizeof(u) * 3];
    577   UChar *end = buf + sizeof(buf) / sizeof(UChar);
    578   UChar *p = end;
    579  
    580   if (u == 0) {
    581     *--p = '0';
    582   } else {
    583     while (u) {
    584       *--p = (unsigned short)((u % 10) + '0');
    585       u /= 10;
    586     }
    587   }
    588  
    589   return UString(p, static_cast<int>(end - p));
    590 }
    591 
    592 UString UString::from(long l)
    593 {
    594   UChar buf[1 + sizeof(l) * 3];
    595   UChar *end = buf + sizeof(buf) / sizeof(UChar);
    596   UChar *p = end;
    597  
    598   if (l == 0) {
    599     *--p = '0';
    600   } else if (l == LONG_MIN) {
    601     char minBuf[1 + sizeof(l) * 3];
    602     sprintf(minBuf, "%ld", LONG_MIN);
    603     return UString(minBuf);
    604   } else {
    605     bool negative = false;
    606     if (l < 0) {
    607       negative = true;
    608       l = -l;
    609     }
    610     while (l) {
    611       *--p = (unsigned short)((l % 10) + '0');
    612       l /= 10;
    613     }
    614     if (negative) {
    615       *--p = '-';
    616     }
    617   }
    618  
    619   return UString(p, static_cast<int>(end - p));
    620 }
    621 
    622 UString UString::from(double d)
    623 {
    624   // avoid ever printing -NaN, in JS conceptually there is only one NaN value
    625   if (isnan(d))
    626     return "NaN";
    627 
    628   char buf[80];
    629   int decimalPoint;
    630   int sign;
    631  
    632   char *result = dtoa(d, 0, &decimalPoint, &sign, NULL);
    633   int length = static_cast<int>(strlen(result));
    634  
    635   int i = 0;
    636   if (sign) {
    637     buf[i++] = '-';
    638   }
    639  
    640   if (decimalPoint <= 0 && decimalPoint > -6) {
    641     buf[i++] = '0';
    642     buf[i++] = '.';
    643     for (int j = decimalPoint; j < 0; j++) {
    644       buf[i++] = '0';
    645     }
    646     strcpy(buf + i, result);
    647   } else if (decimalPoint <= 21 && decimalPoint > 0) {
    648     if (length <= decimalPoint) {
    649       strcpy(buf + i, result);
    650       i += length;
    651       for (int j = 0; j < decimalPoint - length; j++) {
     633    if (decimalPoint <= 0 && decimalPoint > -6) {
    652634        buf[i++] = '0';
    653       }
    654       buf[i] = '\0';
     635        buf[i++] = '.';
     636        for (int j = decimalPoint; j < 0; j++)
     637            buf[i++] = '0';
     638        strcpy(buf + i, result);
     639    } else if (decimalPoint <= 21 && decimalPoint > 0) {
     640        if (length <= decimalPoint) {
     641            strcpy(buf + i, result);
     642            i += length;
     643            for (int j = 0; j < decimalPoint - length; j++)
     644                buf[i++] = '0';
     645            buf[i] = '\0';
     646        } else {
     647            strncpy(buf + i, result, decimalPoint);
     648            i += decimalPoint;
     649            buf[i++] = '.';
     650            strcpy(buf + i, result + decimalPoint);
     651        }
     652    } else if (result[0] < '0' || result[0] > '9')
     653        strcpy(buf + i, result);
     654    else {
     655        buf[i++] = result[0];
     656        if (length > 1) {
     657            buf[i++] = '.';
     658            strcpy(buf + i, result + 1);
     659            i += length - 1;
     660        }
     661       
     662        buf[i++] = 'e';
     663        buf[i++] = (decimalPoint >= 0) ? '+' : '-';
     664        // decimalPoint can't be more than 3 digits decimal given the
     665        // nature of float representation
     666        int exponential = decimalPoint - 1;
     667        if (exponential < 0)
     668            exponential = -exponential;
     669        if (exponential >= 100)
     670            buf[i++] = static_cast<char>('0' + exponential / 100);
     671        if (exponential >= 10)
     672            buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
     673        buf[i++] = static_cast<char>('0' + exponential % 10);
     674        buf[i++] = '\0';
     675    }
     676   
     677  freedtoa(result);
     678
     679  return UString(buf);
     680}
     681
     682UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
     683{
     684    if (rangeCount == 1 && separatorCount == 0) {
     685        int thisSize = size();
     686        int position = substringRanges[0].position;
     687        int length = substringRanges[0].length;
     688        if (position <= 0 && length >= thisSize)
     689            return *this;
     690        return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
     691    }
     692
     693    int totalLength = 0;
     694    for (int i = 0; i < rangeCount; i++)
     695        totalLength += substringRanges[i].length;
     696    for (int i = 0; i < separatorCount; i++)
     697        totalLength += separators[i].size();
     698
     699    if (totalLength == 0)
     700        return "";
     701
     702    UChar* buffer = allocChars(totalLength);
     703    if (!buffer)
     704        return null();
     705
     706    int maxCount = max(rangeCount, separatorCount);
     707    int bufferPos = 0;
     708    for (int i = 0; i < maxCount; i++) {
     709        if (i < rangeCount) {
     710            memcpy(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length * sizeof(UChar));
     711            bufferPos += substringRanges[i].length;
     712        }
     713        if (i < separatorCount) {
     714            memcpy(buffer + bufferPos, separators[i].data(), separators[i].size() * sizeof(UChar));
     715            bufferPos += separators[i].size();
     716        }
     717    }
     718
     719    return UString::Rep::create(buffer, totalLength);
     720}
     721
     722UString& UString::append(const UString &t)
     723{
     724    int thisSize = size();
     725    int thisOffset = m_rep->offset;
     726    int tSize = t.size();
     727    int length = thisSize + tSize;
     728
     729    // possible cases:
     730    if (thisSize == 0) {
     731        // this is empty
     732        *this = t;
     733    } else if (tSize == 0) {
     734        // t is empty
     735    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     736        // this is direct and has refcount of 1 (so we can just alter it directly)
     737        expandCapacity(thisOffset + length);
     738        if (data()) {
     739            memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
     740            m_rep->len = length;
     741            m_rep->_hash = 0;
     742        }
     743    } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
     744        // this reaches the end of the buffer - extend it if it's long enough to append to
     745        expandCapacity(thisOffset + length);
     746        if (data()) {
     747            memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
     748            m_rep = Rep::create(m_rep, 0, length);
     749        }
    655750    } else {
    656       strncpy(buf + i, result, decimalPoint);
    657       i += decimalPoint;
    658       buf[i++] = '.';
    659       strcpy(buf + i, result + decimalPoint);
    660     }
    661   } else if (result[0] < '0' || result[0] > '9') {
    662     strcpy(buf + i, result);
    663   } else {
    664     buf[i++] = result[0];
    665     if (length > 1) {
    666       buf[i++] = '.';
    667       strcpy(buf + i, result + 1);
    668       i += length - 1;
    669     }
    670    
    671     buf[i++] = 'e';
    672     buf[i++] = (decimalPoint >= 0) ? '+' : '-';
    673     // decimalPoint can't be more than 3 digits decimal given the
    674     // nature of float representation
    675     int exponential = decimalPoint - 1;
    676     if (exponential < 0)
    677       exponential = -exponential;
    678     if (exponential >= 100)
    679       buf[i++] = static_cast<char>('0' + exponential / 100);
    680     if (exponential >= 10)
    681       buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
    682     buf[i++] = static_cast<char>('0' + exponential % 10);
    683     buf[i++] = '\0';
    684   }
    685 
    686   freedtoa(result);
    687 
    688   return UString(buf);
    689 }
    690 
    691 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const
    692 {
    693   if (rangeCount == 1 && separatorCount == 0) {
     751        // this is shared with someone using more capacity, gotta make a whole new string
     752        size_t newCapacity = expandedSize(length, 0);
     753        UChar* d = allocChars(newCapacity);
     754        if (!d)
     755            m_rep = &Rep::null;
     756        else {
     757            memcpy(d, data(), thisSize * sizeof(UChar));
     758            memcpy(const_cast<UChar*>(d + thisSize), t.data(), tSize * sizeof(UChar));
     759            m_rep = Rep::create(d, length);
     760            m_rep->capacity = newCapacity;
     761        }
     762    }
     763
     764    return *this;
     765}
     766
     767UString& UString::append(const UChar* tData, int tSize)
     768{
    694769    int thisSize = size();
    695     int position = substringRanges[0].position;
    696     int length = substringRanges[0].length;
    697     if (position <= 0 && length >= thisSize)
    698       return *this;
    699     return UString::Rep::create(m_rep, max(0, position), min(thisSize, length));
    700   }
    701 
    702   int totalLength = 0;
    703   for (int i = 0; i < rangeCount; i++)
    704     totalLength += substringRanges[i].length;
    705   for (int i = 0; i < separatorCount; i++)
    706     totalLength += separators[i].size();
    707 
    708   if (totalLength == 0)
    709     return "";
    710 
    711   UChar* buffer = allocChars(totalLength);
    712   if (!buffer)
    713       return null();
    714 
    715   int maxCount = max(rangeCount, separatorCount);
    716   int bufferPos = 0;
    717   for (int i = 0; i < maxCount; i++) {
    718     if (i < rangeCount) {
    719       memcpy(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length * sizeof(UChar));
    720       bufferPos += substringRanges[i].length;
    721     }
    722     if (i < separatorCount) {
    723       memcpy(buffer + bufferPos, separators[i].data(), separators[i].size() * sizeof(UChar));
    724       bufferPos += separators[i].size();
    725     }
    726   }
    727 
    728   return UString::Rep::create(buffer, totalLength);
    729 }
    730 
    731 UString& UString::append(const UString &t)
    732 {
    733   int thisSize = size();
    734   int thisOffset = m_rep->offset;
    735   int tSize = t.size();
    736   int length = thisSize + tSize;
    737 
    738   // possible cases:
    739   if (thisSize == 0) {
    740     // this is empty
    741     *this = t;
    742   } else if (tSize == 0) {
    743     // t is empty
    744   } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
    745     // this is direct and has refcount of 1 (so we can just alter it directly)
    746     expandCapacity(thisOffset + length);
    747     if (data()) {
    748         memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
    749         m_rep->len = length;
    750         m_rep->_hash = 0;
    751     }
    752   } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
    753     // this reaches the end of the buffer - extend it if it's long enough to append to
    754     expandCapacity(thisOffset + length);
    755     if (data()) {
    756         memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));
    757         m_rep = Rep::create(m_rep, 0, length);
    758     }
    759   } else {
    760     // this is shared with someone using more capacity, gotta make a whole new string
    761     size_t newCapacity = expandedSize(length, 0);
    762     UChar* d = allocChars(newCapacity);
    763     if (!d)
    764         m_rep = &Rep::null;
    765     else {
    766         memcpy(d, data(), thisSize * sizeof(UChar));
    767         memcpy(const_cast<UChar*>(d + thisSize), t.data(), tSize * sizeof(UChar));
    768         m_rep = Rep::create(d, length);
    769         m_rep->capacity = newCapacity;
    770     }
    771   }
    772 
    773   return *this;
    774 }
    775 
    776 UString& UString::append(const UChar* tData, int tSize)
    777 {
    778   int thisSize = size();
    779   int thisOffset = m_rep->offset;
    780   int length = thisSize + tSize;
    781 
    782   // possible cases:
    783   if (tSize == 0) {
    784     // t is empty
    785   } else if (thisSize == 0) {
    786     // this is empty
    787     m_rep = Rep::createCopying(tData, tSize);
    788   } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
    789     // this is direct and has refcount of 1 (so we can just alter it directly)
    790     expandCapacity(thisOffset + length);
    791     if (data()) {
    792         memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));
    793         m_rep->len = length;
    794         m_rep->_hash = 0;
    795     }
    796   } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
    797     // this reaches the end of the buffer - extend it if it's long enough to append to
    798     expandCapacity(thisOffset + length);
    799     if (data()) {
    800         memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));
    801         m_rep = Rep::create(m_rep, 0, length);
    802     }
    803   } else {
    804     // this is shared with someone using more capacity, gotta make a whole new string
    805     size_t newCapacity = expandedSize(length, 0);
    806     UChar* d = allocChars(newCapacity);
    807     if (!d)
    808         m_rep = &Rep::null;
    809     else {
    810         memcpy(d, data(), thisSize * sizeof(UChar));
    811         memcpy(const_cast<UChar*>(d + thisSize), tData, tSize * sizeof(UChar));
    812         m_rep = Rep::create(d, length);
    813         m_rep->capacity = newCapacity;
    814     }
    815   }
    816 
    817   return *this;
    818 }
    819 
    820 UString& UString::append(const char *t)
    821 {
    822   int thisSize = size();
    823   int thisOffset = m_rep->offset;
    824   int tSize = static_cast<int>(strlen(t));
    825   int length = thisSize + tSize;
    826 
    827   // possible cases:
    828   if (thisSize == 0) {
    829     // this is empty
    830     *this = t;
    831   } else if (tSize == 0) {
    832     // t is empty, we'll just return *this below.
    833   } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
    834     // this is direct and has refcount of 1 (so we can just alter it directly)
    835     expandCapacity(thisOffset + length);
    836     UChar *d = const_cast<UChar *>(data());
    837     if (d) {
    838         for (int i = 0; i < tSize; ++i)
    839             d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
    840         m_rep->len = length;
    841         m_rep->_hash = 0;
    842     }
    843   } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
    844     // this string reaches the end of the buffer - extend it
    845     expandCapacity(thisOffset + length);
    846     UChar *d = const_cast<UChar *>(data());
    847     if (d) {
    848         for (int i = 0; i < tSize; ++i)
    849             d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
    850         m_rep = Rep::create(m_rep, 0, length);
    851     }
    852   } else {
    853     // this is shared with someone using more capacity, gotta make a whole new string
    854     size_t newCapacity = expandedSize(length, 0);
    855     UChar* d = allocChars(newCapacity);
    856     if (!d)
    857         m_rep = &Rep::null;
    858     else {
    859         memcpy(d, data(), thisSize * sizeof(UChar));
    860         for (int i = 0; i < tSize; ++i)
    861             d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
    862         m_rep = Rep::create(d, length);
    863         m_rep->capacity = newCapacity;
    864     }
    865   }
    866 
    867   return *this;
     770    int thisOffset = m_rep->offset;
     771    int length = thisSize + tSize;
     772
     773    // possible cases:
     774    if (tSize == 0) {
     775        // t is empty
     776    } else if (thisSize == 0) {
     777        // this is empty
     778        m_rep = Rep::createCopying(tData, tSize);
     779    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     780        // this is direct and has refcount of 1 (so we can just alter it directly)
     781        expandCapacity(thisOffset + length);
     782        if (data()) {
     783            memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));
     784            m_rep->len = length;
     785            m_rep->_hash = 0;
     786        }
     787    } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
     788        // this reaches the end of the buffer - extend it if it's long enough to append to
     789        expandCapacity(thisOffset + length);
     790        if (data()) {
     791            memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));
     792            m_rep = Rep::create(m_rep, 0, length);
     793        }
     794    } else {
     795        // this is shared with someone using more capacity, gotta make a whole new string
     796        size_t newCapacity = expandedSize(length, 0);
     797        UChar* d = allocChars(newCapacity);
     798        if (!d)
     799            m_rep = &Rep::null;
     800        else {
     801            memcpy(d, data(), thisSize * sizeof(UChar));
     802            memcpy(const_cast<UChar*>(d + thisSize), tData, tSize * sizeof(UChar));
     803            m_rep = Rep::create(d, length);
     804            m_rep->capacity = newCapacity;
     805        }
     806    }
     807
     808    return *this;
     809}
     810
     811UString& UString::append(const char* t)
     812{
     813    int thisSize = size();
     814    int thisOffset = m_rep->offset;
     815    int tSize = static_cast<int>(strlen(t));
     816    int length = thisSize + tSize;
     817
     818    // possible cases:
     819    if (thisSize == 0) {
     820        // this is empty
     821        *this = t;
     822    } else if (tSize == 0) {
     823        // t is empty, we'll just return *this below.
     824    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     825        // this is direct and has refcount of 1 (so we can just alter it directly)
     826        expandCapacity(thisOffset + length);
     827        UChar* d = const_cast<UChar*>(data());
     828        if (d) {
     829            for (int i = 0; i < tSize; ++i)
     830                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
     831            m_rep->len = length;
     832            m_rep->_hash = 0;
     833        }
     834    } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
     835        // this string reaches the end of the buffer - extend it
     836        expandCapacity(thisOffset + length);
     837        UChar* d = const_cast<UChar*>(data());
     838        if (d) {
     839            for (int i = 0; i < tSize; ++i)
     840                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
     841            m_rep = Rep::create(m_rep, 0, length);
     842        }
     843    } else {
     844        // this is shared with someone using more capacity, gotta make a whole new string
     845        size_t newCapacity = expandedSize(length, 0);
     846        UChar* d = allocChars(newCapacity);
     847        if (!d)
     848            m_rep = &Rep::null;
     849        else {
     850            memcpy(d, data(), thisSize * sizeof(UChar));
     851            for (int i = 0; i < tSize; ++i)
     852                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
     853            m_rep = Rep::create(d, length);
     854            m_rep->capacity = newCapacity;
     855        }
     856    }
     857
     858    return *this;
    868859}
    869860
    870861UString& UString::append(UChar c)
    871862{
    872   int thisOffset = m_rep->offset;
    873   int length = size();
    874 
    875   // possible cases:
    876   if (length == 0) {
    877     // this is empty - must make a new m_rep because we don't want to pollute the shared empty one
    878     size_t newCapacity = expandedSize(1, 0);
    879     UChar* d = allocChars(newCapacity);
    880     if (!d)
    881         m_rep = &Rep::null;
    882     else {
    883         d[0] = c;
    884         m_rep = Rep::create(d, 1);
    885         m_rep->capacity = newCapacity;
    886     }
    887   } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
    888     // this is direct and has refcount of 1 (so we can just alter it directly)
    889     expandCapacity(thisOffset + length + 1);
    890     UChar *d = const_cast<UChar *>(data());
    891     if (d) {
    892         d[length] = c;
    893         m_rep->len = length + 1;
    894         m_rep->_hash = 0;
    895     }
    896   } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
    897     // this reaches the end of the string - extend it and share
    898     expandCapacity(thisOffset + length + 1);
    899     UChar *d = const_cast<UChar *>(data());
    900     if (d) {
    901         d[length] = c;
    902         m_rep = Rep::create(m_rep, 0, length + 1);
    903     }
    904   } else {
    905     // this is shared with someone using more capacity, gotta make a whole new string
    906     size_t newCapacity = expandedSize(length + 1, 0);
    907     UChar* d = allocChars(newCapacity);
    908     if (!d)
    909         m_rep = &Rep::null;
    910     else {
    911         memcpy(d, data(), length * sizeof(UChar));
    912         d[length] = c;
    913         m_rep = Rep::create(d, length + 1);
    914         m_rep->capacity = newCapacity;
    915     }
    916   }
    917 
    918   return *this;
     863    int thisOffset = m_rep->offset;
     864    int length = size();
     865
     866    // possible cases:
     867    if (length == 0) {
     868        // this is empty - must make a new m_rep because we don't want to pollute the shared empty one
     869        size_t newCapacity = expandedSize(1, 0);
     870        UChar* d = allocChars(newCapacity);
     871        if (!d)
     872            m_rep = &Rep::null;
     873        else {
     874            d[0] = c;
     875            m_rep = Rep::create(d, 1);
     876            m_rep->capacity = newCapacity;
     877        }
     878    } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     879        // this is direct and has refcount of 1 (so we can just alter it directly)
     880        expandCapacity(thisOffset + length + 1);
     881        UChar* d = const_cast<UChar*>(data());
     882        if (d) {
     883            d[length] = c;
     884            m_rep->len = length + 1;
     885            m_rep->_hash = 0;
     886        }
     887    } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
     888        // this reaches the end of the string - extend it and share
     889        expandCapacity(thisOffset + length + 1);
     890        UChar* d = const_cast<UChar*>(data());
     891        if (d) {
     892            d[length] = c;
     893            m_rep = Rep::create(m_rep, 0, length + 1);
     894        }
     895    } else {
     896        // this is shared with someone using more capacity, gotta make a whole new string
     897        size_t newCapacity = expandedSize(length + 1, 0);
     898        UChar* d = allocChars(newCapacity);
     899        if (!d)
     900            m_rep = &Rep::null;
     901        else {
     902            memcpy(d, data(), length * sizeof(UChar));
     903            d[length] = c;
     904            m_rep = Rep::create(d, length + 1);
     905            m_rep->capacity = newCapacity;
     906        }
     907    }
     908
     909    return *this;
    919910}
    920911
     
    925916    buffer.resize(neededSize);
    926917    char* buf = buffer.data();
    927  
     918
    928919    UChar ored = 0;
    929920    const UChar* p = data();
     
    938929    }
    939930    *q = '\0';
    940  
     931
    941932    return !(ored & 0xFF00);
    942933}
    943934
    944 char *UString::ascii() const
    945 {
    946   int length = size();
    947   int neededSize = length + 1;
    948   delete[] statBuffer;
    949   statBuffer = new char[neededSize];
    950  
    951   const UChar *p = data();
    952   char *q = statBuffer;
    953   const UChar *limit = p + length;
    954   while (p != limit) {
    955     *q = static_cast<char>(p[0]);
    956     ++p;
    957     ++q;
    958   }
    959   *q = '\0';
    960 
    961   return statBuffer;
    962 }
    963 
    964 UString& UString::operator=(const char *c)
     935char* UString::ascii() const
     936{
     937    int length = size();
     938    int neededSize = length + 1;
     939    delete[] statBuffer;
     940    statBuffer = new char[neededSize];
     941
     942    const UChar* p = data();
     943    char* q = statBuffer;
     944    const UChar* limit = p + length;
     945    while (p != limit) {
     946        *q = static_cast<char>(p[0]);
     947        ++p;
     948        ++q;
     949    }
     950    *q = '\0';
     951
     952    return statBuffer;
     953}
     954
     955UString& UString::operator=(const char* c)
    965956{
    966957    if (!c) {
     
    974965    }
    975966
    976   int l = static_cast<int>(strlen(c));
    977   UChar *d;
    978   if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
    979     d = m_rep->buf;
    980     m_rep->_hash = 0;
    981     m_rep->len = l;
    982   } else {
    983     d = allocChars(l);
    984     if (!d) {
    985         m_rep = &Rep::null;
     967    int l = static_cast<int>(strlen(c));
     968    UChar* d;
     969    if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
     970        d = m_rep->buf;
     971        m_rep->_hash = 0;
     972        m_rep->len = l;
     973    } else {
     974        d = allocChars(l);
     975        if (!d) {
     976            m_rep = &Rep::null;
     977            return *this;
     978        }
     979        m_rep = Rep::create(d, l);
     980    }
     981    for (int i = 0; i < l; i++)
     982        d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
     983
     984    return *this;
     985}
     986
     987bool UString::is8Bit() const
     988{
     989    const UChar* u = data();
     990    const UChar* limit = u + size();
     991    while (u < limit) {
     992        if (u[0] > 0xFF)
     993            return false;
     994        ++u;
     995    }
     996
     997    return true;
     998}
     999
     1000UChar UString::operator[](int pos) const
     1001{
     1002    if (pos >= size())
     1003        return '\0';
     1004    return data()[pos];
     1005}
     1006
     1007double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
     1008{
     1009    double d;
     1010
     1011    // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
     1012    // after the number, so this is too strict a check.
     1013    CStringBuffer s;
     1014    if (!getCString(s))
     1015        return NaN;
     1016    const char* c = s.data();
     1017
     1018    // skip leading white space
     1019    while (isASCIISpace(*c))
     1020        c++;
     1021
     1022    // empty string ?
     1023    if (*c == '\0')
     1024        return tolerateEmptyString ? 0.0 : NaN;
     1025
     1026    // hex number ?
     1027    if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
     1028        const char* firstDigitPosition = c + 2;
     1029        c++;
     1030        d = 0.0;
     1031        while (*(++c)) {
     1032            if (*c >= '0' && *c <= '9')
     1033                d = d * 16.0 + *c - '0';
     1034            else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
     1035                d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
     1036            else
     1037                break;
     1038        }
     1039
     1040        if (d >= mantissaOverflowLowerBound)
     1041            d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
     1042    } else {
     1043        // regular number ?
     1044        char* end;
     1045        d = strtod(c, &end);
     1046        if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
     1047            c = end;
     1048        } else {
     1049            double sign = 1.0;
     1050
     1051            if (*c == '+')
     1052                c++;
     1053            else if (*c == '-') {
     1054                sign = -1.0;
     1055                c++;
     1056            }
     1057
     1058            // We used strtod() to do the conversion. However, strtod() handles
     1059            // infinite values slightly differently than JavaScript in that it
     1060            // converts the string "inf" with any capitalization to infinity,
     1061            // whereas the ECMA spec requires that it be converted to NaN.
     1062
     1063            if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
     1064                d = sign * Inf;
     1065                c += 8;
     1066            } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
     1067                c = end;
     1068            else
     1069                return NaN;
     1070        }
     1071    }
     1072
     1073    // allow trailing white space
     1074    while (isASCIISpace(*c))
     1075        c++;
     1076    // don't allow anything after - unless tolerant=true
     1077    if (!tolerateTrailingJunk && *c != '\0')
     1078        d = NaN;
     1079
     1080    return d;
     1081}
     1082
     1083double UString::toDouble(bool tolerateTrailingJunk) const
     1084{
     1085    return toDouble(tolerateTrailingJunk, true);
     1086}
     1087
     1088double UString::toDouble() const
     1089{
     1090    return toDouble(false, true);
     1091}
     1092
     1093uint32_t UString::toUInt32(bool* ok) const
     1094{
     1095    double d = toDouble();
     1096    bool b = true;
     1097
     1098    if (d != static_cast<uint32_t>(d)) {
     1099        b = false;
     1100        d = 0;
     1101    }
     1102
     1103    if (ok)
     1104        *ok = b;
     1105
     1106    return static_cast<uint32_t>(d);
     1107}
     1108
     1109uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
     1110{
     1111    double d = toDouble(false, tolerateEmptyString);
     1112    bool b = true;
     1113
     1114    if (d != static_cast<uint32_t>(d)) {
     1115        b = false;
     1116        d = 0;
     1117    }
     1118
     1119    if (ok)
     1120        *ok = b;
     1121
     1122    return static_cast<uint32_t>(d);
     1123}
     1124
     1125uint32_t UString::toStrictUInt32(bool* ok) const
     1126{
     1127    if (ok)
     1128        *ok = false;
     1129
     1130    // Empty string is not OK.
     1131    int len = m_rep->len;
     1132    if (len == 0)
     1133        return 0;
     1134    const UChar* p = m_rep->data();
     1135    unsigned short c = p[0];
     1136
     1137    // If the first digit is 0, only 0 itself is OK.
     1138    if (c == '0') {
     1139        if (len == 1 && ok)
     1140            *ok = true;
     1141        return 0;
     1142    }
     1143
     1144    // Convert to UInt32, checking for overflow.
     1145    uint32_t i = 0;
     1146    while (1) {
     1147        // Process character, turning it into a digit.
     1148        if (c < '0' || c > '9')
     1149            return 0;
     1150        const unsigned d = c - '0';
     1151
     1152        // Multiply by 10, checking for overflow out of 32 bits.
     1153        if (i > 0xFFFFFFFFU / 10)
     1154            return 0;
     1155        i *= 10;
     1156
     1157        // Add in the digit, checking for overflow out of 32 bits.
     1158        const unsigned max = 0xFFFFFFFFU - d;
     1159        if (i > max)
     1160            return 0;
     1161        i += d;
     1162
     1163        // Handle end of string.
     1164        if (--len == 0) {
     1165            if (ok)
     1166                *ok = true;
     1167            return i;
     1168        }
     1169
     1170        // Get next character.
     1171        c = *(++p);
     1172    }
     1173}
     1174
     1175int UString::find(const UString& f, int pos) const
     1176{
     1177    int sz = size();
     1178    int fsz = f.size();
     1179    if (sz < fsz)
     1180        return -1;
     1181    if (pos < 0)
     1182        pos = 0;
     1183    if (fsz == 0)
     1184        return pos;
     1185    const UChar* end = data() + sz - fsz;
     1186    int fsizeminusone = (fsz - 1) * sizeof(UChar);
     1187    const UChar* fdata = f.data();
     1188    unsigned short fchar = fdata[0];
     1189    ++fdata;
     1190    for (const UChar* c = data() + pos; c <= end; c++) {
     1191        if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
     1192            return static_cast<int>(c - data());
     1193    }
     1194
     1195    return -1;
     1196}
     1197
     1198int UString::find(UChar ch, int pos) const
     1199{
     1200    if (pos < 0)
     1201        pos = 0;
     1202    const UChar* end = data() + size();
     1203    for (const UChar* c = data() + pos; c < end; c++) {
     1204        if (*c == ch)
     1205            return static_cast<int>(c - data());
     1206    }
     1207   
     1208    return -1;
     1209}
     1210
     1211int UString::rfind(const UString& f, int pos) const
     1212{
     1213    int sz = size();
     1214    int fsz = f.size();
     1215    if (sz < fsz)
     1216        return -1;
     1217    if (pos < 0)
     1218        pos = 0;
     1219    if (pos > sz - fsz)
     1220        pos = sz - fsz;
     1221    if (fsz == 0)
     1222        return pos;
     1223    int fsizeminusone = (fsz - 1) * sizeof(UChar);
     1224    const UChar* fdata = f.data();
     1225    for (const UChar* c = data() + pos; c >= data(); c--) {
     1226        if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
     1227            return static_cast<int>(c - data());
     1228    }
     1229
     1230    return -1;
     1231}
     1232
     1233int UString::rfind(UChar ch, int pos) const
     1234{
     1235    if (isEmpty())
     1236        return -1;
     1237    if (pos + 1 >= size())
     1238        pos = size() - 1;
     1239    for (const UChar* c = data() + pos; c >= data(); c--) {
     1240        if (*c == ch)
     1241            return static_cast<int>(c - data());
     1242    }
     1243
     1244    return -1;
     1245}
     1246
     1247UString UString::substr(int pos, int len) const
     1248{
     1249    int s = size();
     1250
     1251    if (pos < 0)
     1252        pos = 0;
     1253    else if (pos >= s)
     1254        pos = s;
     1255    if (len < 0)
     1256        len = s;
     1257    if (pos + len >= s)
     1258        len = s - pos;
     1259
     1260    if (pos == 0 && len == s)
    9861261        return *this;
    987     }
    988     m_rep = Rep::create(d, l);
    989   }
    990   for (int i = 0; i < l; i++)
    991     d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
    992 
    993   return *this;
    994 }
    995 
    996 bool UString::is8Bit() const
    997 {
    998   const UChar *u = data();
    999   const UChar *limit = u + size();
    1000   while (u < limit) {
    1001     if (u[0] > 0xFF)
    1002       return false;
    1003     ++u;
    1004   }
    1005 
    1006   return true;
    1007 }
    1008 
    1009 UChar UString::operator[](int pos) const
    1010 {
    1011   if (pos >= size())
    1012     return '\0';
    1013   return data()[pos];
    1014 }
    1015 
    1016 double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
    1017 {
    1018   double d;
    1019 
    1020   // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk
    1021   // after the number, so this is too strict a check.
    1022   CStringBuffer s;
    1023   if (!getCString(s))
    1024     return NaN;
    1025   const char* c = s.data();
    1026 
    1027   // skip leading white space
    1028   while (isASCIISpace(*c))
    1029     c++;
    1030 
    1031   // empty string ?
    1032   if (*c == '\0')
    1033     return tolerateEmptyString ? 0.0 : NaN;
    1034 
    1035   // hex number ?
    1036   if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
    1037     const char* firstDigitPosition = c + 2;
    1038     c++;
    1039     d = 0.0;
    1040     while (*(++c)) {
    1041       if (*c >= '0' && *c <= '9')
    1042         d = d * 16.0 + *c - '0';
    1043       else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
    1044         d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
    1045       else
    1046         break;
    1047     }
    1048 
    1049     if (d >= mantissaOverflowLowerBound)
    1050         d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
    1051   } else {
    1052     // regular number ?
    1053     char *end;
    1054     d = strtod(c, &end);
    1055     if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
    1056       c = end;
    1057     } else {
    1058       double sign = 1.0;
    1059 
    1060       if (*c == '+')
    1061         c++;
    1062       else if (*c == '-') {
    1063         sign = -1.0;
    1064         c++;
    1065       }
    1066 
    1067       // We used strtod() to do the conversion. However, strtod() handles
    1068       // infinite values slightly differently than JavaScript in that it
    1069       // converts the string "inf" with any capitalization to infinity,
    1070       // whereas the ECMA spec requires that it be converted to NaN.
    1071 
    1072       if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
    1073         d = sign * Inf;
    1074         c += 8;
    1075       } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
    1076         c = end;
    1077       else
    1078         return NaN;
    1079     }
    1080   }
    1081 
    1082   // allow trailing white space
    1083   while (isASCIISpace(*c))
    1084     c++;
    1085   // don't allow anything after - unless tolerant=true
    1086   if (!tolerateTrailingJunk && *c != '\0')
    1087     d = NaN;
    1088 
    1089   return d;
    1090 }
    1091 
    1092 double UString::toDouble(bool tolerateTrailingJunk) const
    1093 {
    1094   return toDouble(tolerateTrailingJunk, true);
    1095 }
    1096 
    1097 double UString::toDouble() const
    1098 {
    1099   return toDouble(false, true);
    1100 }
    1101 
    1102 uint32_t UString::toUInt32(bool *ok) const
    1103 {
    1104   double d = toDouble();
    1105   bool b = true;
    1106 
    1107   if (d != static_cast<uint32_t>(d)) {
    1108     b = false;
    1109     d = 0;
    1110   }
    1111 
    1112   if (ok)
    1113     *ok = b;
    1114 
    1115   return static_cast<uint32_t>(d);
    1116 }
    1117 
    1118 uint32_t UString::toUInt32(bool *ok, bool tolerateEmptyString) const
    1119 {
    1120   double d = toDouble(false, tolerateEmptyString);
    1121   bool b = true;
    1122 
    1123   if (d != static_cast<uint32_t>(d)) {
    1124     b = false;
    1125     d = 0;
    1126   }
    1127 
    1128   if (ok)
    1129     *ok = b;
    1130 
    1131   return static_cast<uint32_t>(d);
    1132 }
    1133 
    1134 uint32_t UString::toStrictUInt32(bool *ok) const
    1135 {
    1136   if (ok)
    1137     *ok = false;
    1138 
    1139   // Empty string is not OK.
    1140   int len = m_rep->len;
    1141   if (len == 0)
    1142     return 0;
    1143   const UChar *p = m_rep->data();
    1144   unsigned short c = p[0];
    1145 
    1146   // If the first digit is 0, only 0 itself is OK.
    1147   if (c == '0') {
    1148     if (len == 1 && ok)
    1149       *ok = true;
    1150     return 0;
    1151   }
    1152  
    1153   // Convert to UInt32, checking for overflow.
    1154   uint32_t i = 0;
    1155   while (1) {
    1156     // Process character, turning it into a digit.
    1157     if (c < '0' || c > '9')
    1158       return 0;
    1159     const unsigned d = c - '0';
    1160    
    1161     // Multiply by 10, checking for overflow out of 32 bits.
    1162     if (i > 0xFFFFFFFFU / 10)
    1163       return 0;
    1164     i *= 10;
    1165    
    1166     // Add in the digit, checking for overflow out of 32 bits.
    1167     const unsigned max = 0xFFFFFFFFU - d;
    1168     if (i > max)
     1262
     1263    return UString(Rep::create(m_rep, pos, len));
     1264}
     1265
     1266bool operator==(const UString& s1, const UString& s2)
     1267{
     1268    if (s1.m_rep->len != s2.m_rep->len)
     1269        return false;
     1270
     1271    return (memcmp(s1.m_rep->data(), s2.m_rep->data(), s1.m_rep->len * sizeof(UChar)) == 0);
     1272}
     1273
     1274bool operator==(const UString& s1, const char *s2)
     1275{
     1276    if (s2 == 0)
     1277        return s1.isEmpty();
     1278
     1279    const UChar* u = s1.data();
     1280    const UChar* uend = u + s1.size();
     1281    while (u != uend && *s2) {
     1282        if (u[0] != (unsigned char)*s2)
     1283            return false;
     1284        s2++;
     1285        u++;
     1286    }
     1287
     1288    return u == uend && *s2 == 0;
     1289}
     1290
     1291bool operator<(const UString& s1, const UString& s2)
     1292{
     1293    const int l1 = s1.size();
     1294    const int l2 = s2.size();
     1295    const int lmin = l1 < l2 ? l1 : l2;
     1296    const UChar* c1 = s1.data();
     1297    const UChar* c2 = s2.data();
     1298    int l = 0;
     1299    while (l < lmin && *c1 == *c2) {
     1300        c1++;
     1301        c2++;
     1302        l++;
     1303    }
     1304    if (l < lmin)
     1305        return (c1[0] < c2[0]);
     1306
     1307    return (l1 < l2);
     1308}
     1309
     1310bool operator>(const UString& s1, const UString& s2)
     1311{
     1312    const int l1 = s1.size();
     1313    const int l2 = s2.size();
     1314    const int lmin = l1 < l2 ? l1 : l2;
     1315    const UChar* c1 = s1.data();
     1316    const UChar* c2 = s2.data();
     1317    int l = 0;
     1318    while (l < lmin && *c1 == *c2) {
     1319        c1++;
     1320        c2++;
     1321        l++;
     1322    }
     1323    if (l < lmin)
     1324        return (c1[0] > c2[0]);
     1325
     1326    return (l1 > l2);
     1327}
     1328
     1329int compare(const UString& s1, const UString& s2)
     1330{
     1331    const int l1 = s1.size();
     1332    const int l2 = s2.size();
     1333    const int lmin = l1 < l2 ? l1 : l2;
     1334    const UChar* c1 = s1.data();
     1335    const UChar* c2 = s2.data();
     1336    int l = 0;
     1337    while (l < lmin && *c1 == *c2) {
     1338        c1++;
     1339        c2++;
     1340        l++;
     1341    }
     1342
     1343    if (l < lmin)
     1344        return (c1[0] > c2[0]) ? 1 : -1;
     1345
     1346    if (l1 == l2)
    11691347        return 0;
    1170     i += d;
    1171    
    1172     // Handle end of string.
    1173     if (--len == 0) {
    1174       if (ok)
    1175         *ok = true;
    1176       return i;
    1177     }
    1178    
    1179     // Get next character.
    1180     c = *(++p);
    1181   }
    1182 }
    1183 
    1184 int UString::find(const UString &f, int pos) const
    1185 {
    1186   int sz = size();
    1187   int fsz = f.size();
    1188   if (sz < fsz)
    1189     return -1;
    1190   if (pos < 0)
    1191     pos = 0;
    1192   if (fsz == 0)
    1193     return pos;
    1194   const UChar *end = data() + sz - fsz;
    1195   int fsizeminusone = (fsz - 1) * sizeof(UChar);
    1196   const UChar *fdata = f.data();
    1197   unsigned short fchar = fdata[0];
    1198   ++fdata;
    1199   for (const UChar *c = data() + pos; c <= end; c++)
    1200     if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
    1201       return static_cast<int>(c - data());
    1202 
    1203   return -1;
    1204 }
    1205 
    1206 int UString::find(UChar ch, int pos) const
    1207 {
    1208   if (pos < 0)
    1209     pos = 0;
    1210   const UChar *end = data() + size();
    1211   for (const UChar *c = data() + pos; c < end; c++)
    1212     if (*c == ch)
    1213       return static_cast<int>(c - data());
    1214 
    1215   return -1;
    1216 }
    1217 
    1218 int UString::rfind(const UString &f, int pos) const
    1219 {
    1220   int sz = size();
    1221   int fsz = f.size();
    1222   if (sz < fsz)
    1223     return -1;
    1224   if (pos < 0)
    1225     pos = 0;
    1226   if (pos > sz - fsz)
    1227     pos = sz - fsz;
    1228   if (fsz == 0)
    1229     return pos;
    1230   int fsizeminusone = (fsz - 1) * sizeof(UChar);
    1231   const UChar *fdata = f.data();
    1232   for (const UChar *c = data() + pos; c >= data(); c--) {
    1233     if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
    1234       return static_cast<int>(c - data());
    1235   }
    1236 
    1237   return -1;
    1238 }
    1239 
    1240 int UString::rfind(UChar ch, int pos) const
    1241 {
    1242   if (isEmpty())
    1243     return -1;
    1244   if (pos + 1 >= size())
    1245     pos = size() - 1;
    1246   for (const UChar *c = data() + pos; c >= data(); c--) {
    1247     if (*c == ch)
    1248       return static_cast<int>(c-data());
    1249   }
    1250 
    1251   return -1;
    1252 }
    1253 
    1254 UString UString::substr(int pos, int len) const
    1255 {
    1256   int s = size();
    1257 
    1258   if (pos < 0)
    1259     pos = 0;
    1260   else if (pos >= s)
    1261     pos = s;
    1262   if (len < 0)
    1263     len = s;
    1264   if (pos + len >= s)
    1265     len = s - pos;
    1266 
    1267   if (pos == 0 && len == s)
    1268     return *this;
    1269 
    1270   return UString(Rep::create(m_rep, pos, len));
    1271 }
    1272 
    1273 bool operator==(const UString& s1, const UString& s2)
    1274 {
    1275   if (s1.m_rep->len != s2.m_rep->len)
    1276     return false;
    1277 
    1278   return (memcmp(s1.m_rep->data(), s2.m_rep->data(),
    1279                  s1.m_rep->len * sizeof(UChar)) == 0);
    1280 }
    1281 
    1282 bool operator==(const UString& s1, const char *s2)
    1283 {
    1284   if (s2 == 0) {
    1285     return s1.isEmpty();
    1286   }
    1287 
    1288   const UChar *u = s1.data();
    1289   const UChar *uend = u + s1.size();
    1290   while (u != uend && *s2) {
    1291     if (u[0] != (unsigned char)*s2)
    1292       return false;
    1293     s2++;
    1294     u++;
    1295   }
    1296 
    1297   return u == uend && *s2 == 0;
    1298 }
    1299 
    1300 bool operator<(const UString& s1, const UString& s2)
    1301 {
    1302   const int l1 = s1.size();
    1303   const int l2 = s2.size();
    1304   const int lmin = l1 < l2 ? l1 : l2;
    1305   const UChar *c1 = s1.data();
    1306   const UChar *c2 = s2.data();
    1307   int l = 0;
    1308   while (l < lmin && *c1 == *c2) {
    1309     c1++;
    1310     c2++;
    1311     l++;
    1312   }
    1313   if (l < lmin)
    1314     return (c1[0] < c2[0]);
    1315 
    1316   return (l1 < l2);
    1317 }
    1318 
    1319 bool operator>(const UString& s1, const UString& s2)
    1320 {
    1321   const int l1 = s1.size();
    1322   const int l2 = s2.size();
    1323   const int lmin = l1 < l2 ? l1 : l2;
    1324   const UChar *c1 = s1.data();
    1325   const UChar *c2 = s2.data();
    1326   int l = 0;
    1327   while (l < lmin && *c1 == *c2) {
    1328     c1++;
    1329     c2++;
    1330     l++;
    1331   }
    1332   if (l < lmin)
    1333     return (c1[0] > c2[0]);
    1334 
    1335   return (l1 > l2);
    1336 }
    1337 
    1338 int compare(const UString& s1, const UString& s2)
    1339 {
    1340   const int l1 = s1.size();
    1341   const int l2 = s2.size();
    1342   const int lmin = l1 < l2 ? l1 : l2;
    1343   const UChar *c1 = s1.data();
    1344   const UChar *c2 = s2.data();
    1345   int l = 0;
    1346   while (l < lmin && *c1 == *c2) {
    1347     c1++;
    1348     c2++;
    1349     l++;
    1350   }
    1351 
    1352   if (l < lmin)
    1353     return (c1[0] > c2[0]) ? 1 : -1;
    1354 
    1355   if (l1 == l2)
    1356     return 0;
    1357 
    1358   return (l1 > l2) ? 1 : -1;
     1348
     1349    return (l1 > l2) ? 1 : -1;
    13591350}
    13601351
     
    13661357    const UChar* d = r->data();
    13671358    const UChar* s = b->data();
    1368     for (int i = 0; i != length; ++i)
     1359    for (int i = 0; i != length; ++i) {
    13691360        if (d[i] != s[i])
    13701361            return false;
     1362    }
    13711363    return true;
    13721364}
     
    13741366CString UString::UTF8String(bool strict) const
    13751367{
    1376   // Allocate a buffer big enough to hold all the characters.
    1377   const int length = size();
    1378   Vector<char, 1024> buffer(length * 3);
    1379 
    1380   // Convert to runs of 8-bit characters.
    1381   char* p = buffer.data();
    1382   const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
    1383   ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
    1384   if (result != conversionOK)
    1385     return CString();
    1386 
    1387   return CString(buffer.data(), p - buffer.data());
     1368    // Allocate a buffer big enough to hold all the characters.
     1369    const int length = size();
     1370    Vector<char, 1024> buffer(length * 3);
     1371
     1372    // Convert to runs of 8-bit characters.
     1373    char* p = buffer.data();
     1374    const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
     1375    ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
     1376    if (result != conversionOK)
     1377        return CString();
     1378
     1379    return CString(buffer.data(), p - buffer.data());
    13881380}
    13891381
Note: See TracChangeset for help on using the changeset viewer.