Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef StringConcatenate_h
     27 #define StringConcatenate_h
     28 
     29 #include <string.h>
     30 
     31 #ifndef WTFString_h
     32 #include "wtf/text/AtomicString.h"
     33 #endif
     34 
     35 // This macro is helpful for testing how many intermediate Strings are created while evaluating an
     36 // expression containing operator+.
     37 #ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
     38 #define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
     39 #endif
     40 
     41 namespace WTF {
     42 
     43 template<typename StringType>
     44 class StringTypeAdapter {
     45 };
     46 
     47 template<>
     48 class StringTypeAdapter<char> {
     49 public:
     50     StringTypeAdapter<char>(char buffer)
     51         : m_buffer(buffer)
     52     {
     53     }
     54 
     55     unsigned length() { return 1; }
     56 
     57     bool is8Bit() { return true; }
     58 
     59     void writeTo(LChar* destination)
     60     {
     61         *destination = m_buffer;
     62     }
     63 
     64     void writeTo(UChar* destination) { *destination = m_buffer; }
     65 
     66 private:
     67     unsigned char m_buffer;
     68 };
     69 
     70 template<>
     71 class StringTypeAdapter<LChar> {
     72 public:
     73     StringTypeAdapter<LChar>(LChar buffer)
     74         : m_buffer(buffer)
     75     {
     76     }
     77 
     78     unsigned length() { return 1; }
     79 
     80     bool is8Bit() { return true; }
     81 
     82     void writeTo(LChar* destination)
     83     {
     84         *destination = m_buffer;
     85     }
     86 
     87     void writeTo(UChar* destination) { *destination = m_buffer; }
     88 
     89 private:
     90     LChar m_buffer;
     91 };
     92 
     93 template<>
     94 class StringTypeAdapter<UChar> {
     95 public:
     96     StringTypeAdapter<UChar>(UChar buffer)
     97         : m_buffer(buffer)
     98     {
     99     }
    100 
    101     unsigned length() { return 1; }
    102 
    103     bool is8Bit() { return m_buffer <= 0xff; }
    104 
    105     void writeTo(LChar* destination)
    106     {
    107         ASSERT(is8Bit());
    108         *destination = static_cast<LChar>(m_buffer);
    109     }
    110 
    111     void writeTo(UChar* destination) { *destination = m_buffer; }
    112 
    113 private:
    114     UChar m_buffer;
    115 };
    116 
    117 template<>
    118 class StringTypeAdapter<char*> {
    119 public:
    120     StringTypeAdapter<char*>(char* buffer)
    121         : m_buffer(buffer)
    122         , m_length(strlen(buffer))
    123     {
    124     }
    125 
    126     unsigned length() { return m_length; }
    127 
    128     bool is8Bit() { return true; }
    129 
    130     void writeTo(LChar* destination)
    131     {
    132         for (unsigned i = 0; i < m_length; ++i)
    133             destination[i] = static_cast<LChar>(m_buffer[i]);
    134     }
    135 
    136     void writeTo(UChar* destination)
    137     {
    138         for (unsigned i = 0; i < m_length; ++i) {
    139             unsigned char c = m_buffer[i];
    140             destination[i] = c;
    141         }
    142     }
    143 
    144 private:
    145     const char* m_buffer;
    146     unsigned m_length;
    147 };
    148 
    149 template<>
    150 class StringTypeAdapter<LChar*> {
    151 public:
    152     StringTypeAdapter<LChar*>(LChar* buffer)
    153     : m_buffer(buffer)
    154     , m_length(strlen(reinterpret_cast<char*>(buffer)))
    155     {
    156     }
    157 
    158     unsigned length() { return m_length; }
    159 
    160     bool is8Bit() { return true; }
    161 
    162     void writeTo(LChar* destination)
    163     {
    164         memcpy(destination, m_buffer, m_length * sizeof(LChar));
    165     }
    166 
    167     void writeTo(UChar* destination)
    168     {
    169         StringImpl::copyChars(destination, m_buffer, m_length);
    170     }
    171 
    172 private:
    173     const LChar* m_buffer;
    174     unsigned m_length;
    175 };
    176 
    177 template<>
    178 class StringTypeAdapter<const UChar*> {
    179 public:
    180     StringTypeAdapter<const UChar*>(const UChar* buffer)
    181         : m_buffer(buffer)
    182     {
    183         size_t len = 0;
    184         while (m_buffer[len] != UChar(0))
    185             ++len;
    186 
    187         RELEASE_ASSERT(len <= std::numeric_limits<unsigned>::max());
    188 
    189         m_length = len;
    190     }
    191 
    192     unsigned length() { return m_length; }
    193 
    194     bool is8Bit() { return false; }
    195 
    196     NO_RETURN_DUE_TO_CRASH void writeTo(LChar*)
    197     {
    198         RELEASE_ASSERT(false);
    199     }
    200 
    201     void writeTo(UChar* destination)
    202     {
    203         memcpy(destination, m_buffer, m_length * sizeof(UChar));
    204     }
    205 
    206 private:
    207     const UChar* m_buffer;
    208     unsigned m_length;
    209 };
    210 
    211 template<>
    212 class StringTypeAdapter<const char*> {
    213 public:
    214     StringTypeAdapter<const char*>(const char* buffer)
    215         : m_buffer(buffer)
    216         , m_length(strlen(buffer))
    217     {
    218     }
    219 
    220     unsigned length() { return m_length; }
    221 
    222     bool is8Bit() { return true; }
    223 
    224     void writeTo(LChar* destination)
    225     {
    226         memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
    227     }
    228 
    229     void writeTo(UChar* destination)
    230     {
    231         for (unsigned i = 0; i < m_length; ++i) {
    232             unsigned char c = m_buffer[i];
    233             destination[i] = c;
    234         }
    235     }
    236 
    237 private:
    238     const char* m_buffer;
    239     unsigned m_length;
    240 };
    241 
    242 template<>
    243 class StringTypeAdapter<const LChar*> {
    244 public:
    245     StringTypeAdapter<const LChar*>(const LChar* buffer)
    246         : m_buffer(buffer)
    247         , m_length(strlen(reinterpret_cast<const char*>(buffer)))
    248     {
    249     }
    250 
    251     unsigned length() { return m_length; }
    252 
    253     bool is8Bit() { return true; }
    254 
    255     void writeTo(LChar* destination)
    256     {
    257         memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
    258     }
    259 
    260     void writeTo(UChar* destination)
    261     {
    262         StringImpl::copyChars(destination, m_buffer, m_length);
    263     }
    264 
    265 private:
    266     const LChar* m_buffer;
    267     unsigned m_length;
    268 };
    269 
    270 template<>
    271 class StringTypeAdapter<Vector<char> > {
    272 public:
    273     StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
    274         : m_buffer(buffer)
    275     {
    276     }
    277 
    278     size_t length() { return m_buffer.size(); }
    279 
    280     bool is8Bit() { return true; }
    281 
    282     void writeTo(LChar* destination)
    283     {
    284         for (size_t i = 0; i < m_buffer.size(); ++i)
    285             destination[i] = static_cast<unsigned char>(m_buffer[i]);
    286     }
    287 
    288     void writeTo(UChar* destination)
    289     {
    290         for (size_t i = 0; i < m_buffer.size(); ++i)
    291             destination[i] = static_cast<unsigned char>(m_buffer[i]);
    292     }
    293 
    294 private:
    295     const Vector<char>& m_buffer;
    296 };
    297 
    298 template<>
    299 class StringTypeAdapter<Vector<LChar> > {
    300 public:
    301     StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer)
    302         : m_buffer(buffer)
    303     {
    304     }
    305 
    306     size_t length() { return m_buffer.size(); }
    307 
    308     bool is8Bit() { return true; }
    309 
    310     void writeTo(LChar* destination)
    311     {
    312         for (size_t i = 0; i < m_buffer.size(); ++i)
    313             destination[i] = m_buffer[i];
    314     }
    315 
    316     void writeTo(UChar* destination)
    317     {
    318         for (size_t i = 0; i < m_buffer.size(); ++i)
    319             destination[i] = m_buffer[i];
    320     }
    321 
    322 private:
    323     const Vector<LChar>& m_buffer;
    324 };
    325 
    326 template<>
    327 class StringTypeAdapter<String> {
    328 public:
    329     StringTypeAdapter<String>(const String& string)
    330         : m_buffer(string)
    331     {
    332     }
    333 
    334     unsigned length() { return m_buffer.length(); }
    335 
    336     bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
    337 
    338     void writeTo(LChar* destination)
    339     {
    340         unsigned length = m_buffer.length();
    341 
    342         ASSERT(is8Bit());
    343         const LChar* data = m_buffer.characters8();
    344         for (unsigned i = 0; i < length; ++i)
    345             destination[i] = data[i];
    346 
    347         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
    348     }
    349 
    350     void writeTo(UChar* destination)
    351     {
    352         unsigned length = m_buffer.length();
    353 
    354         if (is8Bit()) {
    355             const LChar* data = m_buffer.characters8();
    356             for (unsigned i = 0; i < length; ++i)
    357                 destination[i] = data[i];
    358         } else {
    359             const UChar* data = m_buffer.characters16();
    360             for (unsigned i = 0; i < length; ++i)
    361                 destination[i] = data[i];
    362         }
    363 
    364         WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
    365     }
    366 
    367 private:
    368     const String& m_buffer;
    369 };
    370 
    371 template<>
    372 class StringTypeAdapter<AtomicString> {
    373 public:
    374     StringTypeAdapter<AtomicString>(const AtomicString& string)
    375         : m_adapter(string.string())
    376     {
    377     }
    378 
    379     unsigned length() { return m_adapter.length(); }
    380 
    381     bool is8Bit() { return m_adapter.is8Bit(); }
    382 
    383     void writeTo(LChar* destination) { m_adapter.writeTo(destination); }
    384     void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
    385 
    386 private:
    387     StringTypeAdapter<String> m_adapter;
    388 };
    389 
    390 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
    391 {
    392     unsigned oldTotal = total;
    393     total = oldTotal + addend;
    394     if (total < oldTotal)
    395         overflow = true;
    396 }
    397 
    398 template<typename StringType1, typename StringType2>
    399 PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2)
    400 {
    401     StringTypeAdapter<StringType1> adapter1(string1);
    402     StringTypeAdapter<StringType2> adapter2(string2);
    403 
    404     bool overflow = false;
    405     unsigned length = adapter1.length();
    406     sumWithOverflow(length, adapter2.length(), overflow);
    407     if (overflow)
    408         return 0;
    409 
    410     if (adapter1.is8Bit() && adapter2.is8Bit()) {
    411         LChar* buffer;
    412         RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
    413         if (!resultImpl)
    414             return 0;
    415 
    416         LChar* result = buffer;
    417         adapter1.writeTo(result);
    418         result += adapter1.length();
    419         adapter2.writeTo(result);
    420 
    421         return resultImpl.release();
    422     }
    423 
    424     UChar* buffer;
    425     RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer);
    426     if (!resultImpl)
    427         return 0;
    428 
    429     UChar* result = buffer;
    430     adapter1.writeTo(result);
    431     result += adapter1.length();
    432     adapter2.writeTo(result);
    433 
    434     return resultImpl.release();
    435 }
    436 
    437 } // namespace WTF
    438 
    439 #include "wtf/text/StringOperators.h"
    440 #endif
    441