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 41namespace WTF { 42 43template<typename StringType> 44class StringTypeAdapter { 45}; 46 47template<> 48class StringTypeAdapter<char> { 49public: 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 66private: 67 unsigned char m_buffer; 68}; 69 70template<> 71class StringTypeAdapter<LChar> { 72public: 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 89private: 90 LChar m_buffer; 91}; 92 93template<> 94class StringTypeAdapter<UChar> { 95public: 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 113private: 114 UChar m_buffer; 115}; 116 117template<> 118class WTF_EXPORT StringTypeAdapter<char*> { 119public: 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 void writeTo(UChar* destination); 133 134private: 135 const char* m_buffer; 136 unsigned m_length; 137}; 138 139template<> 140class WTF_EXPORT StringTypeAdapter<LChar*> { 141public: 142 StringTypeAdapter<LChar*>(LChar* buffer); 143 144 unsigned length() { return m_length; } 145 146 bool is8Bit() { return true; } 147 148 void writeTo(LChar* destination); 149 150 void writeTo(UChar* destination); 151 152private: 153 const LChar* m_buffer; 154 unsigned m_length; 155}; 156 157template<> 158class WTF_EXPORT StringTypeAdapter<const UChar*> { 159public: 160 StringTypeAdapter(const UChar* buffer); 161 162 unsigned length() { return m_length; } 163 164 bool is8Bit() { return false; } 165 166 NO_RETURN_DUE_TO_CRASH void writeTo(LChar*) 167 { 168 RELEASE_ASSERT(false); 169 } 170 171 void writeTo(UChar* destination); 172 173private: 174 const UChar* m_buffer; 175 unsigned m_length; 176}; 177 178template<> 179class WTF_EXPORT StringTypeAdapter<const char*> { 180public: 181 StringTypeAdapter<const char*>(const char* buffer); 182 183 unsigned length() { return m_length; } 184 185 bool is8Bit() { return true; } 186 187 void writeTo(LChar* destination); 188 189 void writeTo(UChar* destination); 190 191private: 192 const char* m_buffer; 193 unsigned m_length; 194}; 195 196template<> 197class WTF_EXPORT StringTypeAdapter<const LChar*> { 198public: 199 StringTypeAdapter<const LChar*>(const LChar* buffer); 200 201 unsigned length() { return m_length; } 202 203 bool is8Bit() { return true; } 204 205 void writeTo(LChar* destination); 206 207 void writeTo(UChar* destination); 208 209private: 210 const LChar* m_buffer; 211 unsigned m_length; 212}; 213 214template<> 215class WTF_EXPORT StringTypeAdapter<Vector<char> > { 216public: 217 StringTypeAdapter<Vector<char> >(const Vector<char>& buffer) 218 : m_buffer(buffer) 219 { 220 } 221 222 size_t length() { return m_buffer.size(); } 223 224 bool is8Bit() { return true; } 225 226 void writeTo(LChar* destination); 227 228 void writeTo(UChar* destination); 229 230private: 231 const Vector<char>& m_buffer; 232}; 233 234template<> 235class StringTypeAdapter<Vector<LChar> > { 236public: 237 StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer) 238 : m_buffer(buffer) 239 { 240 } 241 242 size_t length() { return m_buffer.size(); } 243 244 bool is8Bit() { return true; } 245 246 void writeTo(LChar* destination); 247 248 void writeTo(UChar* destination); 249 250private: 251 const Vector<LChar>& m_buffer; 252}; 253 254template<> 255class WTF_EXPORT StringTypeAdapter<String> { 256public: 257 StringTypeAdapter<String>(const String& string) 258 : m_buffer(string) 259 { 260 } 261 262 unsigned length() { return m_buffer.length(); } 263 264 bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); } 265 266 void writeTo(LChar* destination); 267 268 void writeTo(UChar* destination); 269 270private: 271 const String& m_buffer; 272}; 273 274template<> 275class StringTypeAdapter<AtomicString> { 276public: 277 StringTypeAdapter<AtomicString>(const AtomicString& string) 278 : m_adapter(string.string()) 279 { 280 } 281 282 unsigned length() { return m_adapter.length(); } 283 284 bool is8Bit() { return m_adapter.is8Bit(); } 285 286 void writeTo(LChar* destination) { m_adapter.writeTo(destination); } 287 void writeTo(UChar* destination) { m_adapter.writeTo(destination); } 288 289private: 290 StringTypeAdapter<String> m_adapter; 291}; 292 293inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) 294{ 295 unsigned oldTotal = total; 296 total = oldTotal + addend; 297 if (total < oldTotal) 298 overflow = true; 299} 300 301template<typename StringType1, typename StringType2> 302PassRefPtr<StringImpl> makeString(StringType1 string1, StringType2 string2) 303{ 304 StringTypeAdapter<StringType1> adapter1(string1); 305 StringTypeAdapter<StringType2> adapter2(string2); 306 307 bool overflow = false; 308 unsigned length = adapter1.length(); 309 sumWithOverflow(length, adapter2.length(), overflow); 310 if (overflow) 311 return nullptr; 312 313 if (adapter1.is8Bit() && adapter2.is8Bit()) { 314 LChar* buffer; 315 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer); 316 if (!resultImpl) 317 return nullptr; 318 319 LChar* result = buffer; 320 adapter1.writeTo(result); 321 result += adapter1.length(); 322 adapter2.writeTo(result); 323 324 return resultImpl.release(); 325 } 326 327 UChar* buffer; 328 RefPtr<StringImpl> resultImpl = StringImpl::createUninitialized(length, buffer); 329 if (!resultImpl) 330 return nullptr; 331 332 UChar* result = buffer; 333 adapter1.writeTo(result); 334 result += adapter1.length(); 335 adapter2.writeTo(result); 336 337 return resultImpl.release(); 338} 339 340} // namespace WTF 341 342#include "wtf/text/StringOperators.h" 343#endif 344