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 <wtf/text/WTFString.h> 30 31 namespace WTF { 32 33 template<typename StringType> 34 class StringTypeAdapter { 35 }; 36 37 template<> 38 class StringTypeAdapter<char> { 39 public: 40 StringTypeAdapter<char>(char buffer) 41 : m_buffer(buffer) 42 { 43 } 44 45 unsigned length() { return 1; } 46 void writeTo(UChar* destination) { *destination = m_buffer; } 47 48 private: 49 unsigned char m_buffer; 50 }; 51 52 template<> 53 class StringTypeAdapter<UChar> { 54 public: 55 StringTypeAdapter<UChar>(UChar buffer) 56 : m_buffer(buffer) 57 { 58 } 59 60 unsigned length() { return 1; } 61 void writeTo(UChar* destination) { *destination = m_buffer; } 62 63 private: 64 UChar m_buffer; 65 }; 66 67 template<> 68 class StringTypeAdapter<char*> { 69 public: 70 StringTypeAdapter<char*>(char* buffer) 71 : m_buffer(buffer) 72 , m_length(strlen(buffer)) 73 { 74 } 75 76 unsigned length() { return m_length; } 77 78 void writeTo(UChar* destination) 79 { 80 for (unsigned i = 0; i < m_length; ++i) { 81 unsigned char c = m_buffer[i]; 82 destination[i] = c; 83 } 84 } 85 86 private: 87 const char* m_buffer; 88 unsigned m_length; 89 }; 90 91 template<> 92 class StringTypeAdapter<const UChar*> { 93 public: 94 StringTypeAdapter<const UChar*>(const UChar* buffer) 95 : m_buffer(buffer) 96 { 97 size_t len = 0; 98 while (m_buffer[len] != UChar(0)) 99 len++; 100 101 if (len > std::numeric_limits<unsigned>::max()) 102 CRASH(); 103 104 m_length = len; 105 } 106 107 unsigned length() { return m_length; } 108 109 void writeTo(UChar* destination) 110 { 111 memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(UChar)); 112 } 113 114 private: 115 const UChar* m_buffer; 116 unsigned m_length; 117 }; 118 119 template<> 120 class StringTypeAdapter<const char*> { 121 public: 122 StringTypeAdapter<const char*>(const char* buffer) 123 : m_buffer(buffer) 124 , m_length(strlen(buffer)) 125 { 126 } 127 128 unsigned length() { return m_length; } 129 130 void writeTo(UChar* destination) 131 { 132 for (unsigned i = 0; i < m_length; ++i) { 133 unsigned char c = m_buffer[i]; 134 destination[i] = c; 135 } 136 } 137 138 private: 139 const char* m_buffer; 140 unsigned m_length; 141 }; 142 143 template<> 144 class StringTypeAdapter<Vector<char> > { 145 public: 146 StringTypeAdapter<Vector<char> >(const Vector<char>& buffer) 147 : m_buffer(buffer) 148 { 149 } 150 151 size_t length() { return m_buffer.size(); } 152 153 void writeTo(UChar* destination) 154 { 155 for (size_t i = 0; i < m_buffer.size(); ++i) { 156 unsigned char c = m_buffer[i]; 157 destination[i] = c; 158 } 159 } 160 161 private: 162 const Vector<char>& m_buffer; 163 }; 164 165 template<> 166 class StringTypeAdapter<String> { 167 public: 168 StringTypeAdapter<String>(const String& string) 169 : m_buffer(string) 170 { 171 } 172 173 unsigned length() { return m_buffer.length(); } 174 175 void writeTo(UChar* destination) 176 { 177 const UChar* data = m_buffer.characters(); 178 unsigned length = m_buffer.length(); 179 for (unsigned i = 0; i < length; ++i) 180 destination[i] = data[i]; 181 } 182 183 private: 184 const String& m_buffer; 185 }; 186 187 inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) 188 { 189 unsigned oldTotal = total; 190 total = oldTotal + addend; 191 if (total < oldTotal) 192 overflow = true; 193 } 194 195 template<typename StringType1, typename StringType2> 196 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2) 197 { 198 StringTypeAdapter<StringType1> adapter1(string1); 199 StringTypeAdapter<StringType2> adapter2(string2); 200 201 UChar* buffer; 202 bool overflow = false; 203 unsigned length = adapter1.length(); 204 sumWithOverflow(length, adapter2.length(), overflow); 205 if (overflow) 206 return 0; 207 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 208 if (!resultImpl) 209 return 0; 210 211 UChar* result = buffer; 212 adapter1.writeTo(result); 213 result += adapter1.length(); 214 adapter2.writeTo(result); 215 216 return resultImpl.release(); 217 } 218 219 template<typename StringType1, typename StringType2, typename StringType3> 220 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) 221 { 222 StringTypeAdapter<StringType1> adapter1(string1); 223 StringTypeAdapter<StringType2> adapter2(string2); 224 StringTypeAdapter<StringType3> adapter3(string3); 225 226 UChar* buffer = 0; 227 bool overflow = false; 228 unsigned length = adapter1.length(); 229 sumWithOverflow(length, adapter2.length(), overflow); 230 sumWithOverflow(length, adapter3.length(), overflow); 231 if (overflow) 232 return 0; 233 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 234 if (!resultImpl) 235 return 0; 236 237 UChar* result = buffer; 238 adapter1.writeTo(result); 239 result += adapter1.length(); 240 adapter2.writeTo(result); 241 result += adapter2.length(); 242 adapter3.writeTo(result); 243 244 return resultImpl.release(); 245 } 246 247 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> 248 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) 249 { 250 StringTypeAdapter<StringType1> adapter1(string1); 251 StringTypeAdapter<StringType2> adapter2(string2); 252 StringTypeAdapter<StringType3> adapter3(string3); 253 StringTypeAdapter<StringType4> adapter4(string4); 254 255 UChar* buffer; 256 bool overflow = false; 257 unsigned length = adapter1.length(); 258 sumWithOverflow(length, adapter2.length(), overflow); 259 sumWithOverflow(length, adapter3.length(), overflow); 260 sumWithOverflow(length, adapter4.length(), overflow); 261 if (overflow) 262 return 0; 263 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 264 if (!resultImpl) 265 return 0; 266 267 UChar* result = buffer; 268 adapter1.writeTo(result); 269 result += adapter1.length(); 270 adapter2.writeTo(result); 271 result += adapter2.length(); 272 adapter3.writeTo(result); 273 result += adapter3.length(); 274 adapter4.writeTo(result); 275 276 return resultImpl.release(); 277 } 278 279 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> 280 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) 281 { 282 StringTypeAdapter<StringType1> adapter1(string1); 283 StringTypeAdapter<StringType2> adapter2(string2); 284 StringTypeAdapter<StringType3> adapter3(string3); 285 StringTypeAdapter<StringType4> adapter4(string4); 286 StringTypeAdapter<StringType5> adapter5(string5); 287 288 UChar* buffer; 289 bool overflow = false; 290 unsigned length = adapter1.length(); 291 sumWithOverflow(length, adapter2.length(), overflow); 292 sumWithOverflow(length, adapter3.length(), overflow); 293 sumWithOverflow(length, adapter4.length(), overflow); 294 sumWithOverflow(length, adapter5.length(), overflow); 295 if (overflow) 296 return 0; 297 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 298 if (!resultImpl) 299 return 0; 300 301 UChar* result = buffer; 302 adapter1.writeTo(result); 303 result += adapter1.length(); 304 adapter2.writeTo(result); 305 result += adapter2.length(); 306 adapter3.writeTo(result); 307 result += adapter3.length(); 308 adapter4.writeTo(result); 309 result += adapter4.length(); 310 adapter5.writeTo(result); 311 312 return resultImpl.release(); 313 } 314 315 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> 316 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) 317 { 318 StringTypeAdapter<StringType1> adapter1(string1); 319 StringTypeAdapter<StringType2> adapter2(string2); 320 StringTypeAdapter<StringType3> adapter3(string3); 321 StringTypeAdapter<StringType4> adapter4(string4); 322 StringTypeAdapter<StringType5> adapter5(string5); 323 StringTypeAdapter<StringType6> adapter6(string6); 324 325 UChar* buffer; 326 bool overflow = false; 327 unsigned length = adapter1.length(); 328 sumWithOverflow(length, adapter2.length(), overflow); 329 sumWithOverflow(length, adapter3.length(), overflow); 330 sumWithOverflow(length, adapter4.length(), overflow); 331 sumWithOverflow(length, adapter5.length(), overflow); 332 sumWithOverflow(length, adapter6.length(), overflow); 333 if (overflow) 334 return 0; 335 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 336 if (!resultImpl) 337 return 0; 338 339 UChar* result = buffer; 340 adapter1.writeTo(result); 341 result += adapter1.length(); 342 adapter2.writeTo(result); 343 result += adapter2.length(); 344 adapter3.writeTo(result); 345 result += adapter3.length(); 346 adapter4.writeTo(result); 347 result += adapter4.length(); 348 adapter5.writeTo(result); 349 result += adapter5.length(); 350 adapter6.writeTo(result); 351 352 return resultImpl.release(); 353 } 354 355 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> 356 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) 357 { 358 StringTypeAdapter<StringType1> adapter1(string1); 359 StringTypeAdapter<StringType2> adapter2(string2); 360 StringTypeAdapter<StringType3> adapter3(string3); 361 StringTypeAdapter<StringType4> adapter4(string4); 362 StringTypeAdapter<StringType5> adapter5(string5); 363 StringTypeAdapter<StringType6> adapter6(string6); 364 StringTypeAdapter<StringType7> adapter7(string7); 365 366 UChar* buffer; 367 bool overflow = false; 368 unsigned length = adapter1.length(); 369 sumWithOverflow(length, adapter2.length(), overflow); 370 sumWithOverflow(length, adapter3.length(), overflow); 371 sumWithOverflow(length, adapter4.length(), overflow); 372 sumWithOverflow(length, adapter5.length(), overflow); 373 sumWithOverflow(length, adapter6.length(), overflow); 374 sumWithOverflow(length, adapter7.length(), overflow); 375 if (overflow) 376 return 0; 377 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 378 if (!resultImpl) 379 return 0; 380 381 UChar* result = buffer; 382 adapter1.writeTo(result); 383 result += adapter1.length(); 384 adapter2.writeTo(result); 385 result += adapter2.length(); 386 adapter3.writeTo(result); 387 result += adapter3.length(); 388 adapter4.writeTo(result); 389 result += adapter4.length(); 390 adapter5.writeTo(result); 391 result += adapter5.length(); 392 adapter6.writeTo(result); 393 result += adapter6.length(); 394 adapter7.writeTo(result); 395 396 return resultImpl.release(); 397 } 398 399 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> 400 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) 401 { 402 StringTypeAdapter<StringType1> adapter1(string1); 403 StringTypeAdapter<StringType2> adapter2(string2); 404 StringTypeAdapter<StringType3> adapter3(string3); 405 StringTypeAdapter<StringType4> adapter4(string4); 406 StringTypeAdapter<StringType5> adapter5(string5); 407 StringTypeAdapter<StringType6> adapter6(string6); 408 StringTypeAdapter<StringType7> adapter7(string7); 409 StringTypeAdapter<StringType8> adapter8(string8); 410 411 UChar* buffer; 412 bool overflow = false; 413 unsigned length = adapter1.length(); 414 sumWithOverflow(length, adapter2.length(), overflow); 415 sumWithOverflow(length, adapter3.length(), overflow); 416 sumWithOverflow(length, adapter4.length(), overflow); 417 sumWithOverflow(length, adapter5.length(), overflow); 418 sumWithOverflow(length, adapter6.length(), overflow); 419 sumWithOverflow(length, adapter7.length(), overflow); 420 sumWithOverflow(length, adapter8.length(), overflow); 421 if (overflow) 422 return 0; 423 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 424 if (!resultImpl) 425 return 0; 426 427 UChar* result = buffer; 428 adapter1.writeTo(result); 429 result += adapter1.length(); 430 adapter2.writeTo(result); 431 result += adapter2.length(); 432 adapter3.writeTo(result); 433 result += adapter3.length(); 434 adapter4.writeTo(result); 435 result += adapter4.length(); 436 adapter5.writeTo(result); 437 result += adapter5.length(); 438 adapter6.writeTo(result); 439 result += adapter6.length(); 440 adapter7.writeTo(result); 441 result += adapter7.length(); 442 adapter8.writeTo(result); 443 444 return resultImpl.release(); 445 } 446 447 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> 448 PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) 449 { 450 StringTypeAdapter<StringType1> adapter1(string1); 451 StringTypeAdapter<StringType2> adapter2(string2); 452 StringTypeAdapter<StringType3> adapter3(string3); 453 StringTypeAdapter<StringType4> adapter4(string4); 454 StringTypeAdapter<StringType5> adapter5(string5); 455 StringTypeAdapter<StringType6> adapter6(string6); 456 StringTypeAdapter<StringType7> adapter7(string7); 457 StringTypeAdapter<StringType8> adapter8(string8); 458 StringTypeAdapter<StringType9> adapter9(string9); 459 460 UChar* buffer; 461 bool overflow = false; 462 unsigned length = adapter1.length(); 463 sumWithOverflow(length, adapter2.length(), overflow); 464 sumWithOverflow(length, adapter3.length(), overflow); 465 sumWithOverflow(length, adapter4.length(), overflow); 466 sumWithOverflow(length, adapter5.length(), overflow); 467 sumWithOverflow(length, adapter6.length(), overflow); 468 sumWithOverflow(length, adapter7.length(), overflow); 469 sumWithOverflow(length, adapter8.length(), overflow); 470 sumWithOverflow(length, adapter9.length(), overflow); 471 if (overflow) 472 return 0; 473 RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); 474 if (!resultImpl) 475 return 0; 476 477 UChar* result = buffer; 478 adapter1.writeTo(result); 479 result += adapter1.length(); 480 adapter2.writeTo(result); 481 result += adapter2.length(); 482 adapter3.writeTo(result); 483 result += adapter3.length(); 484 adapter4.writeTo(result); 485 result += adapter4.length(); 486 adapter5.writeTo(result); 487 result += adapter5.length(); 488 adapter6.writeTo(result); 489 result += adapter6.length(); 490 adapter7.writeTo(result); 491 result += adapter7.length(); 492 adapter8.writeTo(result); 493 result += adapter8.length(); 494 adapter9.writeTo(result); 495 496 return resultImpl.release(); 497 } 498 499 500 // Convenience only. 501 template<typename StringType1> 502 String makeString(StringType1 string1) 503 { 504 return String(string1); 505 } 506 507 template<typename StringType1, typename StringType2> 508 String makeString(StringType1 string1, StringType2 string2) 509 { 510 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); 511 if (!resultImpl) 512 CRASH(); 513 return resultImpl.release(); 514 } 515 516 template<typename StringType1, typename StringType2, typename StringType3> 517 String makeString(StringType1 string1, StringType2 string2, StringType3 string3) 518 { 519 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3); 520 if (!resultImpl) 521 CRASH(); 522 return resultImpl.release(); 523 } 524 525 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> 526 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) 527 { 528 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); 529 if (!resultImpl) 530 CRASH(); 531 return resultImpl.release(); 532 } 533 534 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> 535 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) 536 { 537 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); 538 if (!resultImpl) 539 CRASH(); 540 return resultImpl.release(); 541 } 542 543 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> 544 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) 545 { 546 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); 547 if (!resultImpl) 548 CRASH(); 549 return resultImpl.release(); 550 } 551 552 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> 553 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) 554 { 555 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); 556 if (!resultImpl) 557 CRASH(); 558 return resultImpl.release(); 559 } 560 561 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> 562 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) 563 { 564 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); 565 if (!resultImpl) 566 CRASH(); 567 return resultImpl.release(); 568 } 569 570 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> 571 String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) 572 { 573 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9); 574 if (!resultImpl) 575 CRASH(); 576 return resultImpl.release(); 577 } 578 579 } // namespace WTF 580 581 using WTF::makeString; 582 583 #endif 584