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