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 31namespace WTF { 32 33template<typename StringType> 34class StringTypeAdapter { 35}; 36 37template<> 38class StringTypeAdapter<char> { 39public: 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 48private: 49 unsigned char m_buffer; 50}; 51 52template<> 53class StringTypeAdapter<UChar> { 54public: 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 63private: 64 UChar m_buffer; 65}; 66 67template<> 68class StringTypeAdapter<char*> { 69public: 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 86private: 87 const char* m_buffer; 88 unsigned m_length; 89}; 90 91template<> 92class StringTypeAdapter<const UChar*> { 93public: 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 114private: 115 const UChar* m_buffer; 116 unsigned m_length; 117}; 118 119template<> 120class StringTypeAdapter<const char*> { 121public: 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 138private: 139 const char* m_buffer; 140 unsigned m_length; 141}; 142 143template<> 144class StringTypeAdapter<Vector<char> > { 145public: 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 161private: 162 const Vector<char>& m_buffer; 163}; 164 165template<> 166class StringTypeAdapter<String> { 167public: 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 183private: 184 const String& m_buffer; 185}; 186 187inline 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 195template<typename StringType1, typename StringType2> 196PassRefPtr<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 219template<typename StringType1, typename StringType2, typename StringType3> 220PassRefPtr<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 247template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> 248PassRefPtr<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 279template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> 280PassRefPtr<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 315template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> 316PassRefPtr<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 355template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> 356PassRefPtr<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 399template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> 400PassRefPtr<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 447template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> 448PassRefPtr<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. 501template<typename StringType1> 502String makeString(StringType1 string1) 503{ 504 return String(string1); 505} 506 507template<typename StringType1, typename StringType2> 508String makeString(StringType1 string1, StringType2 string2) 509{ 510 RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); 511 if (!resultImpl) 512 CRASH(); 513 return resultImpl.release(); 514} 515 516template<typename StringType1, typename StringType2, typename StringType3> 517String 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 525template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> 526String 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 534template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> 535String 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 543template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> 544String 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 552template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> 553String 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 561template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> 562String 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 570template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> 571String 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 581using WTF::makeString; 582 583#endif 584