string.h (31545B)
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #pragma once 23 24 #include <initializer_list> 25 #include "array.h" 26 #include <string.h> 27 28 KJ_BEGIN_HEADER 29 30 namespace kj { 31 class StringPtr; 32 class String; 33 34 class StringTree; // string-tree.h 35 } 36 37 constexpr kj::StringPtr operator "" _kj(const char* str, size_t n); 38 // You can append _kj to a string literal to make its type be StringPtr. There are a few cases 39 // where you must do this for correctness: 40 // - When you want to declare a constexpr StringPtr. Without _kj, this is a compile error. 41 // - When you want to initialize a static/global StringPtr from a string literal without forcing 42 // global constructor code to run at dynamic initialization time. 43 // - When you have a string literal that contains NUL characters. Without _kj, the string will 44 // be considered to end at the first NUL. 45 // - When you want to initialize an ArrayPtr<const char> from a string literal, without including 46 // the NUL terminator in the data. (Initializing an ArrayPtr from a regular string literal is 47 // a compile error specifically due to this ambiguity.) 48 // 49 // In other cases, there should be no difference between initializing a StringPtr from a regular 50 // string literal vs. one with _kj (assuming the compiler is able to optimize away strlen() on a 51 // string literal). 52 53 namespace kj { 54 55 // Our STL string SFINAE trick does not work with GCC 4.7, but it works with Clang and GCC 4.8, so 56 // we'll just preprocess it out if not supported. 57 #if __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || _MSC_VER 58 #define KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP 1 59 #endif 60 61 // ======================================================================================= 62 // StringPtr -- A NUL-terminated ArrayPtr<const char> containing UTF-8 text. 63 // 64 // NUL bytes are allowed to appear before the end of the string. The only requirement is that 65 // a NUL byte appear immediately after the last byte of the content. This terminator byte is not 66 // counted in the string's size. 67 68 class StringPtr { 69 public: 70 inline StringPtr(): content("", 1) {} 71 inline StringPtr(decltype(nullptr)): content("", 1) {} 72 inline StringPtr(const char* value KJ_LIFETIMEBOUND): content(value, strlen(value) + 1) {} 73 inline StringPtr(const char* value KJ_LIFETIMEBOUND, size_t size): content(value, size + 1) { 74 KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated."); 75 } 76 inline StringPtr(const char* begin KJ_LIFETIMEBOUND, const char* end KJ_LIFETIMEBOUND): StringPtr(begin, end - begin) {} 77 inline StringPtr(String&& value KJ_LIFETIMEBOUND) : StringPtr(value) {} 78 inline StringPtr(const String& value KJ_LIFETIMEBOUND); 79 StringPtr& operator=(String&& value) = delete; 80 inline StringPtr& operator=(decltype(nullptr)) { 81 content = ArrayPtr<const char>("", 1); 82 return *this; 83 } 84 85 #if __cpp_char8_t 86 inline StringPtr(const char8_t* value KJ_LIFETIMEBOUND): StringPtr(reinterpret_cast<const char*>(value)) {} 87 inline StringPtr(const char8_t* value KJ_LIFETIMEBOUND, size_t size) 88 : StringPtr(reinterpret_cast<const char*>(value), size) {} 89 inline StringPtr(const char8_t* begin KJ_LIFETIMEBOUND, const char8_t* end KJ_LIFETIMEBOUND) 90 : StringPtr(reinterpret_cast<const char*>(begin), reinterpret_cast<const char*>(end)) {} 91 // KJ strings are and always have been UTF-8, so screw this C++20 char8_t stuff. 92 #endif 93 94 #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP 95 template <typename T, typename = decltype(instance<T>().c_str())> 96 inline StringPtr(const T& t KJ_LIFETIMEBOUND): StringPtr(t.c_str()) {} 97 // Allow implicit conversion from any class that has a c_str() method (namely, std::string). 98 // We use a template trick to detect std::string in order to avoid including the header for 99 // those who don't want it. 100 101 template <typename T, typename = decltype(instance<T>().c_str())> 102 inline operator T() const { return cStr(); } 103 // Allow implicit conversion to any class that has a c_str() method (namely, std::string). 104 // We use a template trick to detect std::string in order to avoid including the header for 105 // those who don't want it. 106 #endif 107 108 inline constexpr operator ArrayPtr<const char>() const; 109 inline constexpr ArrayPtr<const char> asArray() const; 110 inline ArrayPtr<const byte> asBytes() const { return asArray().asBytes(); } 111 // Result does not include NUL terminator. 112 113 inline const char* cStr() const { return content.begin(); } 114 // Returns NUL-terminated string. 115 116 inline size_t size() const { return content.size() - 1; } 117 // Result does not include NUL terminator. 118 119 inline char operator[](size_t index) const { return content[index]; } 120 121 inline constexpr const char* begin() const { return content.begin(); } 122 inline constexpr const char* end() const { return content.end() - 1; } 123 124 inline constexpr bool operator==(decltype(nullptr)) const { return content.size() <= 1; } 125 inline constexpr bool operator!=(decltype(nullptr)) const { return content.size() > 1; } 126 127 inline bool operator==(const StringPtr& other) const; 128 inline bool operator!=(const StringPtr& other) const { return !(*this == other); } 129 inline bool operator< (const StringPtr& other) const; 130 inline bool operator> (const StringPtr& other) const { return other < *this; } 131 inline bool operator<=(const StringPtr& other) const { return !(other < *this); } 132 inline bool operator>=(const StringPtr& other) const { return !(*this < other); } 133 134 inline StringPtr slice(size_t start) const; 135 inline ArrayPtr<const char> slice(size_t start, size_t end) const; 136 // A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter 137 // version that assumes end = size(). 138 139 inline bool startsWith(const StringPtr& other) const; 140 inline bool endsWith(const StringPtr& other) const; 141 142 inline Maybe<size_t> findFirst(char c) const; 143 inline Maybe<size_t> findLast(char c) const; 144 145 template <typename T> 146 T parseAs() const; 147 // Parse string as template number type. 148 // Integer numbers prefixed by "0x" and "0X" are parsed in base 16 (like strtoi with base 0). 149 // Integer numbers prefixed by "0" are parsed in base 10 (unlike strtoi with base 0). 150 // Overflowed integer numbers throw exception. 151 // Overflowed floating numbers return inf. 152 153 private: 154 inline explicit constexpr StringPtr(ArrayPtr<const char> content): content(content) {} 155 156 ArrayPtr<const char> content; 157 158 friend constexpr kj::StringPtr (::operator "" _kj)(const char* str, size_t n); 159 friend class SourceLocation; 160 }; 161 162 #if !__cpp_impl_three_way_comparison 163 inline bool operator==(const char* a, const StringPtr& b) { return b == a; } 164 inline bool operator!=(const char* a, const StringPtr& b) { return b != a; } 165 #endif 166 167 template <> char StringPtr::parseAs<char>() const; 168 template <> signed char StringPtr::parseAs<signed char>() const; 169 template <> unsigned char StringPtr::parseAs<unsigned char>() const; 170 template <> short StringPtr::parseAs<short>() const; 171 template <> unsigned short StringPtr::parseAs<unsigned short>() const; 172 template <> int StringPtr::parseAs<int>() const; 173 template <> unsigned StringPtr::parseAs<unsigned>() const; 174 template <> long StringPtr::parseAs<long>() const; 175 template <> unsigned long StringPtr::parseAs<unsigned long>() const; 176 template <> long long StringPtr::parseAs<long long>() const; 177 template <> unsigned long long StringPtr::parseAs<unsigned long long>() const; 178 template <> float StringPtr::parseAs<float>() const; 179 template <> double StringPtr::parseAs<double>() const; 180 181 // ======================================================================================= 182 // String -- A NUL-terminated Array<char> containing UTF-8 text. 183 // 184 // NUL bytes are allowed to appear before the end of the string. The only requirement is that 185 // a NUL byte appear immediately after the last byte of the content. This terminator byte is not 186 // counted in the string's size. 187 // 188 // To allocate a String, you must call kj::heapString(). We do not implement implicit copying to 189 // the heap because this hides potential inefficiency from the developer. 190 191 class String { 192 public: 193 String() = default; 194 inline String(decltype(nullptr)): content(nullptr) {} 195 inline String(char* value, size_t size, const ArrayDisposer& disposer); 196 // Does not copy. `size` does not include NUL terminator, but `value` must be NUL-terminated. 197 inline explicit String(Array<char> buffer); 198 // Does not copy. Requires `buffer` ends with `\0`. 199 200 inline operator ArrayPtr<char>() KJ_LIFETIMEBOUND; 201 inline operator ArrayPtr<const char>() const KJ_LIFETIMEBOUND; 202 inline ArrayPtr<char> asArray() KJ_LIFETIMEBOUND; 203 inline ArrayPtr<const char> asArray() const KJ_LIFETIMEBOUND; 204 inline ArrayPtr<byte> asBytes() KJ_LIFETIMEBOUND { return asArray().asBytes(); } 205 inline ArrayPtr<const byte> asBytes() const KJ_LIFETIMEBOUND { return asArray().asBytes(); } 206 // Result does not include NUL terminator. 207 208 inline StringPtr asPtr() const KJ_LIFETIMEBOUND { 209 // Convenience operator to return a StringPtr. 210 return StringPtr{*this}; 211 } 212 213 inline Array<char> releaseArray() { return kj::mv(content); } 214 // Disowns the backing array (which includes the NUL terminator) and returns it. The String value 215 // is clobbered (as if moved away). 216 217 inline const char* cStr() const KJ_LIFETIMEBOUND; 218 219 inline size_t size() const; 220 // Result does not include NUL terminator. 221 222 inline char operator[](size_t index) const; 223 inline char& operator[](size_t index) KJ_LIFETIMEBOUND; 224 225 inline char* begin() KJ_LIFETIMEBOUND; 226 inline char* end() KJ_LIFETIMEBOUND; 227 inline const char* begin() const KJ_LIFETIMEBOUND; 228 inline const char* end() const KJ_LIFETIMEBOUND; 229 230 inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; } 231 inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; } 232 233 inline bool operator==(const StringPtr& other) const { return StringPtr(*this) == other; } 234 inline bool operator!=(const StringPtr& other) const { return StringPtr(*this) != other; } 235 inline bool operator< (const StringPtr& other) const { return StringPtr(*this) < other; } 236 inline bool operator> (const StringPtr& other) const { return StringPtr(*this) > other; } 237 inline bool operator<=(const StringPtr& other) const { return StringPtr(*this) <= other; } 238 inline bool operator>=(const StringPtr& other) const { return StringPtr(*this) >= other; } 239 240 inline bool operator==(const String& other) const { return StringPtr(*this) == StringPtr(other); } 241 inline bool operator!=(const String& other) const { return StringPtr(*this) != StringPtr(other); } 242 inline bool operator< (const String& other) const { return StringPtr(*this) < StringPtr(other); } 243 inline bool operator> (const String& other) const { return StringPtr(*this) > StringPtr(other); } 244 inline bool operator<=(const String& other) const { return StringPtr(*this) <= StringPtr(other); } 245 inline bool operator>=(const String& other) const { return StringPtr(*this) >= StringPtr(other); } 246 // Note that if we don't overload for `const String&` specifically, then C++20 will decide that 247 // comparisons between two strings are ambiguous. (Clang turns this into a warning, 248 // -Wambiguous-reversed-operator, due to the stupidity...) 249 250 inline bool startsWith(const StringPtr& other) const { return StringPtr(*this).startsWith(other);} 251 inline bool endsWith(const StringPtr& other) const { return StringPtr(*this).endsWith(other); } 252 253 inline StringPtr slice(size_t start) const KJ_LIFETIMEBOUND { 254 return StringPtr(*this).slice(start); 255 } 256 inline ArrayPtr<const char> slice(size_t start, size_t end) const KJ_LIFETIMEBOUND { 257 return StringPtr(*this).slice(start, end); 258 } 259 260 inline Maybe<size_t> findFirst(char c) const { return StringPtr(*this).findFirst(c); } 261 inline Maybe<size_t> findLast(char c) const { return StringPtr(*this).findLast(c); } 262 263 template <typename T> 264 T parseAs() const { return StringPtr(*this).parseAs<T>(); } 265 // Parse as number 266 267 private: 268 Array<char> content; 269 }; 270 271 #if !__cpp_impl_three_way_comparison 272 inline bool operator==(const char* a, const String& b) { return b == a; } 273 inline bool operator!=(const char* a, const String& b) { return b != a; } 274 #endif 275 276 String heapString(size_t size); 277 // Allocate a String of the given size on the heap, not including NUL terminator. The NUL 278 // terminator will be initialized automatically but the rest of the content is not initialized. 279 280 String heapString(const char* value); 281 String heapString(const char* value, size_t size); 282 String heapString(StringPtr value); 283 String heapString(const String& value); 284 String heapString(ArrayPtr<const char> value); 285 // Allocates a copy of the given value on the heap. 286 287 // ======================================================================================= 288 // Magic str() function which transforms parameters to text and concatenates them into one big 289 // String. 290 291 namespace _ { // private 292 293 inline size_t sum(std::initializer_list<size_t> nums) { 294 size_t result = 0; 295 for (auto num: nums) { 296 result += num; 297 } 298 return result; 299 } 300 301 inline char* fill(char* ptr) { return ptr; } 302 inline char* fillLimited(char* ptr, char* limit) { return ptr; } 303 304 template <typename... Rest> 305 char* fill(char* __restrict__ target, const StringTree& first, Rest&&... rest); 306 template <typename... Rest> 307 char* fillLimited(char* __restrict__ target, char* limit, const StringTree& first, Rest&&... rest); 308 // Make str() work with stringifiers that return StringTree by patching fill(). 309 // 310 // Defined in string-tree.h. 311 312 template <typename First, typename... Rest> 313 char* fill(char* __restrict__ target, const First& first, Rest&&... rest) { 314 auto i = first.begin(); 315 auto end = first.end(); 316 while (i != end) { 317 *target++ = *i++; 318 } 319 return fill(target, kj::fwd<Rest>(rest)...); 320 } 321 322 template <typename... Params> 323 String concat(Params&&... params) { 324 // Concatenate a bunch of containers into a single Array. The containers can be anything that 325 // is iterable and whose elements can be converted to `char`. 326 327 String result = heapString(sum({params.size()...})); 328 fill(result.begin(), kj::fwd<Params>(params)...); 329 return result; 330 } 331 332 inline String concat(String&& arr) { 333 return kj::mv(arr); 334 } 335 336 template <typename First, typename... Rest> 337 char* fillLimited(char* __restrict__ target, char* limit, const First& first, Rest&&... rest) { 338 auto i = first.begin(); 339 auto end = first.end(); 340 while (i != end) { 341 if (target == limit) return target; 342 *target++ = *i++; 343 } 344 return fillLimited(target, limit, kj::fwd<Rest>(rest)...); 345 } 346 347 template <typename T> 348 class Delimited; 349 // Delimits a sequence of type T with a string delimiter. Implements kj::delimited(). 350 351 template <typename T, typename... Rest> 352 char* fill(char* __restrict__ target, Delimited<T>&& first, Rest&&... rest); 353 template <typename T, typename... Rest> 354 char* fillLimited(char* __restrict__ target, char* limit, Delimited<T>&& first,Rest&&... rest); 355 template <typename T, typename... Rest> 356 char* fill(char* __restrict__ target, Delimited<T>& first, Rest&&... rest); 357 template <typename T, typename... Rest> 358 char* fillLimited(char* __restrict__ target, char* limit, Delimited<T>& first,Rest&&... rest); 359 // As with StringTree, we special-case Delimited<T>. 360 361 struct Stringifier { 362 // This is a dummy type with only one instance: STR (below). To make an arbitrary type 363 // stringifiable, define `operator*(Stringifier, T)` to return an iterable container of `char`. 364 // The container type must have a `size()` method. Be sure to declare the operator in the same 365 // namespace as `T` **or** in the global scope. 366 // 367 // A more usual way to accomplish what we're doing here would be to require that you define 368 // a function like `toString(T)` and then rely on argument-dependent lookup. However, this has 369 // the problem that it pollutes other people's namespaces and even the global namespace. For 370 // example, some other project may already have functions called `toString` which do something 371 // different. Declaring `operator*` with `Stringifier` as the left operand cannot conflict with 372 // anything. 373 374 inline ArrayPtr<const char> operator*(ArrayPtr<const char> s) const { return s; } 375 inline ArrayPtr<const char> operator*(ArrayPtr<char> s) const { return s; } 376 inline ArrayPtr<const char> operator*(const Array<const char>& s) const KJ_LIFETIMEBOUND { 377 return s; 378 } 379 inline ArrayPtr<const char> operator*(const Array<char>& s) const KJ_LIFETIMEBOUND { return s; } 380 template<size_t n> 381 inline ArrayPtr<const char> operator*(const CappedArray<char, n>& s) const KJ_LIFETIMEBOUND { 382 return s; 383 } 384 template<size_t n> 385 inline ArrayPtr<const char> operator*(const FixedArray<char, n>& s) const KJ_LIFETIMEBOUND { 386 return s; 387 } 388 inline ArrayPtr<const char> operator*(const char* s) const KJ_LIFETIMEBOUND { 389 return arrayPtr(s, strlen(s)); 390 } 391 #if __cpp_char8_t 392 inline ArrayPtr<const char> operator*(const char8_t* s) const KJ_LIFETIMEBOUND { 393 return operator*(reinterpret_cast<const char*>(s)); 394 } 395 #endif 396 inline ArrayPtr<const char> operator*(const String& s) const KJ_LIFETIMEBOUND { 397 return s.asArray(); 398 } 399 inline ArrayPtr<const char> operator*(const StringPtr& s) const { return s.asArray(); } 400 401 inline Range<char> operator*(const Range<char>& r) const { return r; } 402 inline Repeat<char> operator*(const Repeat<char>& r) const { return r; } 403 404 inline FixedArray<char, 1> operator*(char c) const { 405 FixedArray<char, 1> result; 406 result[0] = c; 407 return result; 408 } 409 410 StringPtr operator*(decltype(nullptr)) const; 411 StringPtr operator*(bool b) const; 412 413 CappedArray<char, 5> operator*(signed char i) const; 414 CappedArray<char, 5> operator*(unsigned char i) const; 415 CappedArray<char, sizeof(short) * 3 + 2> operator*(short i) const; 416 CappedArray<char, sizeof(unsigned short) * 3 + 2> operator*(unsigned short i) const; 417 CappedArray<char, sizeof(int) * 3 + 2> operator*(int i) const; 418 CappedArray<char, sizeof(unsigned int) * 3 + 2> operator*(unsigned int i) const; 419 CappedArray<char, sizeof(long) * 3 + 2> operator*(long i) const; 420 CappedArray<char, sizeof(unsigned long) * 3 + 2> operator*(unsigned long i) const; 421 CappedArray<char, sizeof(long long) * 3 + 2> operator*(long long i) const; 422 CappedArray<char, sizeof(unsigned long long) * 3 + 2> operator*(unsigned long long i) const; 423 CappedArray<char, 24> operator*(float f) const; 424 CappedArray<char, 32> operator*(double f) const; 425 CappedArray<char, sizeof(const void*) * 2 + 1> operator*(const void* s) const; 426 427 #if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP // supports expression SFINAE? 428 template <typename T, typename Result = decltype(instance<T>().toString())> 429 inline Result operator*(T&& value) const { return kj::fwd<T>(value).toString(); } 430 #endif 431 }; 432 static KJ_CONSTEXPR(const) Stringifier STR = Stringifier(); 433 434 } // namespace _ (private) 435 436 template <typename T> 437 auto toCharSequence(T&& value) -> decltype(_::STR * kj::fwd<T>(value)) { 438 // Returns an iterable of chars that represent a textual representation of the value, suitable 439 // for debugging. 440 // 441 // Most users should use str() instead, but toCharSequence() may occasionally be useful to avoid 442 // heap allocation overhead that str() implies. 443 // 444 // To specialize this function for your type, see KJ_STRINGIFY. 445 446 return _::STR * kj::fwd<T>(value); 447 } 448 449 CappedArray<char, sizeof(unsigned char) * 2 + 1> hex(unsigned char i); 450 CappedArray<char, sizeof(unsigned short) * 2 + 1> hex(unsigned short i); 451 CappedArray<char, sizeof(unsigned int) * 2 + 1> hex(unsigned int i); 452 CappedArray<char, sizeof(unsigned long) * 2 + 1> hex(unsigned long i); 453 CappedArray<char, sizeof(unsigned long long) * 2 + 1> hex(unsigned long long i); 454 455 template <typename... Params> 456 String str(Params&&... params) { 457 // Magic function which builds a string from a bunch of arbitrary values. Example: 458 // str(1, " / ", 2, " = ", 0.5) 459 // returns: 460 // "1 / 2 = 0.5" 461 // To teach `str` how to stringify a type, see `Stringifier`. 462 463 return _::concat(toCharSequence(kj::fwd<Params>(params))...); 464 } 465 466 inline String str(String&& s) { return mv(s); } 467 // Overload to prevent redundant allocation. 468 469 template <typename T> 470 _::Delimited<T> delimited(T&& arr, kj::StringPtr delim); 471 // Use to stringify an array. 472 473 template <typename T> 474 String strArray(T&& arr, const char* delim) { 475 size_t delimLen = strlen(delim); 476 KJ_STACK_ARRAY(decltype(_::STR * arr[0]), pieces, kj::size(arr), 8, 32); 477 size_t size = 0; 478 for (size_t i = 0; i < kj::size(arr); i++) { 479 if (i > 0) size += delimLen; 480 pieces[i] = _::STR * arr[i]; 481 size += pieces[i].size(); 482 } 483 484 String result = heapString(size); 485 char* pos = result.begin(); 486 for (size_t i = 0; i < kj::size(arr); i++) { 487 if (i > 0) { 488 memcpy(pos, delim, delimLen); 489 pos += delimLen; 490 } 491 pos = _::fill(pos, pieces[i]); 492 } 493 return result; 494 } 495 496 template <typename... Params> 497 StringPtr strPreallocated(ArrayPtr<char> buffer, Params&&... params) { 498 // Like str() but writes into a preallocated buffer. If the buffer is not long enough, the result 499 // is truncated (but still NUL-terminated). 500 // 501 // This can be used like: 502 // 503 // char buffer[256]; 504 // StringPtr text = strPreallocated(buffer, params...); 505 // 506 // This is useful for optimization. It can also potentially be used safely in async signal 507 // handlers. HOWEVER, to use in an async signal handler, all of the stringifiers for the inputs 508 // must also be signal-safe. KJ guarantees signal safety when stringifying any built-in integer 509 // type (but NOT floating-points), basic char/byte sequences (ArrayPtr<byte>, String, etc.), as 510 // well as Array<T> as long as T can also be stringified safely. To safely stringify a delimited 511 // array, you must use kj::delimited(arr, delim) rather than the deprecated 512 // kj::strArray(arr, delim). 513 514 char* end = _::fillLimited(buffer.begin(), buffer.end() - 1, 515 toCharSequence(kj::fwd<Params>(params))...); 516 *end = '\0'; 517 return StringPtr(buffer.begin(), end); 518 } 519 520 template <typename T, typename = decltype(toCharSequence(kj::instance<T&>()))> 521 inline _::Delimited<ArrayPtr<T>> operator*(const _::Stringifier&, ArrayPtr<T> arr) { 522 return _::Delimited<ArrayPtr<T>>(arr, ", "); 523 } 524 525 template <typename T, typename = decltype(toCharSequence(kj::instance<const T&>()))> 526 inline _::Delimited<ArrayPtr<const T>> operator*(const _::Stringifier&, const Array<T>& arr) { 527 return _::Delimited<ArrayPtr<const T>>(arr, ", "); 528 } 529 530 #define KJ_STRINGIFY(...) operator*(::kj::_::Stringifier, __VA_ARGS__) 531 // Defines a stringifier for a custom type. Example: 532 // 533 // class Foo {...}; 534 // inline StringPtr KJ_STRINGIFY(const Foo& foo) { return foo.name(); } 535 // // or perhaps 536 // inline String KJ_STRINGIFY(const Foo& foo) { return kj::str(foo.fld1(), ",", foo.fld2()); } 537 // 538 // This allows Foo to be passed to str(). 539 // 540 // The function should be declared either in the same namespace as the target type or in the global 541 // namespace. It can return any type which is an iterable container of chars. 542 543 // ======================================================================================= 544 // Inline implementation details. 545 546 inline StringPtr::StringPtr(const String& value): content(value.cStr(), value.size() + 1) {} 547 548 inline constexpr StringPtr::operator ArrayPtr<const char>() const { 549 return ArrayPtr<const char>(content.begin(), content.size() - 1); 550 } 551 552 inline constexpr ArrayPtr<const char> StringPtr::asArray() const { 553 return ArrayPtr<const char>(content.begin(), content.size() - 1); 554 } 555 556 inline bool StringPtr::operator==(const StringPtr& other) const { 557 return content.size() == other.content.size() && 558 memcmp(content.begin(), other.content.begin(), content.size() - 1) == 0; 559 } 560 561 inline bool StringPtr::operator<(const StringPtr& other) const { 562 bool shorter = content.size() < other.content.size(); 563 int cmp = memcmp(content.begin(), other.content.begin(), 564 shorter ? content.size() : other.content.size()); 565 return cmp < 0 || (cmp == 0 && shorter); 566 } 567 568 inline StringPtr StringPtr::slice(size_t start) const { 569 return StringPtr(content.slice(start, content.size())); 570 } 571 inline ArrayPtr<const char> StringPtr::slice(size_t start, size_t end) const { 572 return content.slice(start, end); 573 } 574 575 inline bool StringPtr::startsWith(const StringPtr& other) const { 576 return other.content.size() <= content.size() && 577 memcmp(content.begin(), other.content.begin(), other.size()) == 0; 578 } 579 inline bool StringPtr::endsWith(const StringPtr& other) const { 580 return other.content.size() <= content.size() && 581 memcmp(end() - other.size(), other.content.begin(), other.size()) == 0; 582 } 583 584 inline Maybe<size_t> StringPtr::findFirst(char c) const { 585 const char* pos = reinterpret_cast<const char*>(memchr(content.begin(), c, size())); 586 if (pos == nullptr) { 587 return nullptr; 588 } else { 589 return pos - content.begin(); 590 } 591 } 592 593 inline Maybe<size_t> StringPtr::findLast(char c) const { 594 for (size_t i = size(); i > 0; --i) { 595 if (content[i-1] == c) { 596 return i-1; 597 } 598 } 599 return nullptr; 600 } 601 602 inline String::operator ArrayPtr<char>() { 603 return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1); 604 } 605 inline String::operator ArrayPtr<const char>() const { 606 return content == nullptr ? ArrayPtr<const char>(nullptr) : content.slice(0, content.size() - 1); 607 } 608 609 inline ArrayPtr<char> String::asArray() { 610 return content == nullptr ? ArrayPtr<char>(nullptr) : content.slice(0, content.size() - 1); 611 } 612 inline ArrayPtr<const char> String::asArray() const { 613 return content == nullptr ? ArrayPtr<const char>(nullptr) : content.slice(0, content.size() - 1); 614 } 615 616 inline const char* String::cStr() const { return content == nullptr ? "" : content.begin(); } 617 618 inline size_t String::size() const { return content == nullptr ? 0 : content.size() - 1; } 619 620 inline char String::operator[](size_t index) const { return content[index]; } 621 inline char& String::operator[](size_t index) { return content[index]; } 622 623 inline char* String::begin() { return content == nullptr ? nullptr : content.begin(); } 624 inline char* String::end() { return content == nullptr ? nullptr : content.end() - 1; } 625 inline const char* String::begin() const { return content == nullptr ? nullptr : content.begin(); } 626 inline const char* String::end() const { return content == nullptr ? nullptr : content.end() - 1; } 627 628 inline String::String(char* value, size_t size, const ArrayDisposer& disposer) 629 : content(value, size + 1, disposer) { 630 KJ_IREQUIRE(value[size] == '\0', "String must be NUL-terminated."); 631 } 632 633 inline String::String(Array<char> buffer): content(kj::mv(buffer)) { 634 KJ_IREQUIRE(content.size() > 0 && content.back() == '\0', "String must be NUL-terminated."); 635 } 636 637 inline String heapString(const char* value) { 638 return heapString(value, strlen(value)); 639 } 640 inline String heapString(StringPtr value) { 641 return heapString(value.begin(), value.size()); 642 } 643 inline String heapString(const String& value) { 644 return heapString(value.begin(), value.size()); 645 } 646 inline String heapString(ArrayPtr<const char> value) { 647 return heapString(value.begin(), value.size()); 648 } 649 650 namespace _ { // private 651 652 template <typename T> 653 class Delimited { 654 public: 655 Delimited(T array, kj::StringPtr delimiter) 656 : array(kj::fwd<T>(array)), delimiter(delimiter) {} 657 658 // TODO(someday): In theory we should support iteration as a character sequence, but the iterator 659 // will be pretty complicated. 660 661 size_t size() { 662 ensureStringifiedInitialized(); 663 664 size_t result = 0; 665 bool first = true; 666 for (auto& e: stringified) { 667 if (first) { 668 first = false; 669 } else { 670 result += delimiter.size(); 671 } 672 result += e.size(); 673 } 674 return result; 675 } 676 677 char* flattenTo(char* __restrict__ target) { 678 ensureStringifiedInitialized(); 679 680 bool first = true; 681 for (auto& elem: stringified) { 682 if (first) { 683 first = false; 684 } else { 685 target = fill(target, delimiter); 686 } 687 target = fill(target, elem); 688 } 689 return target; 690 } 691 692 char* flattenTo(char* __restrict__ target, char* limit) { 693 // This is called in the strPreallocated(). We want to avoid allocation. size() will not have 694 // been called in this case, so hopefully `stringified` is still uninitialized. We will 695 // stringify each item and immediately use it. 696 bool first = true; 697 for (auto&& elem: array) { 698 if (target == limit) return target; 699 if (first) { 700 first = false; 701 } else { 702 target = fillLimited(target, limit, delimiter); 703 } 704 target = fillLimited(target, limit, kj::toCharSequence(elem)); 705 } 706 return target; 707 } 708 709 private: 710 typedef decltype(toCharSequence(*instance<T>().begin())) StringifiedItem; 711 T array; 712 kj::StringPtr delimiter; 713 Array<StringifiedItem> stringified; 714 715 void ensureStringifiedInitialized() { 716 if (array.size() > 0 && stringified.size() == 0) { 717 stringified = KJ_MAP(e, array) { return toCharSequence(e); }; 718 } 719 } 720 }; 721 722 template <typename T, typename... Rest> 723 char* fill(char* __restrict__ target, Delimited<T>&& first, Rest&&... rest) { 724 target = first.flattenTo(target); 725 return fill(target, kj::fwd<Rest>(rest)...); 726 } 727 template <typename T, typename... Rest> 728 char* fillLimited(char* __restrict__ target, char* limit, Delimited<T>&& first, Rest&&... rest) { 729 target = first.flattenTo(target, limit); 730 return fillLimited(target, limit, kj::fwd<Rest>(rest)...); 731 } 732 template <typename T, typename... Rest> 733 char* fill(char* __restrict__ target, Delimited<T>& first, Rest&&... rest) { 734 target = first.flattenTo(target); 735 return fill(target, kj::fwd<Rest>(rest)...); 736 } 737 template <typename T, typename... Rest> 738 char* fillLimited(char* __restrict__ target, char* limit, Delimited<T>& first, Rest&&... rest) { 739 target = first.flattenTo(target, limit); 740 return fillLimited(target, limit, kj::fwd<Rest>(rest)...); 741 } 742 743 template <typename T> 744 inline Delimited<T>&& KJ_STRINGIFY(Delimited<T>&& delimited) { return kj::mv(delimited); } 745 template <typename T> 746 inline const Delimited<T>& KJ_STRINGIFY(const Delimited<T>& delimited) { return delimited; } 747 748 } // namespace _ (private) 749 750 template <typename T> 751 _::Delimited<T> delimited(T&& arr, kj::StringPtr delim) { 752 return _::Delimited<T>(kj::fwd<T>(arr), delim); 753 } 754 755 } // namespace kj 756 757 constexpr kj::StringPtr operator "" _kj(const char* str, size_t n) { 758 return kj::StringPtr(kj::ArrayPtr<const char>(str, n + 1)); 759 }; 760 761 KJ_END_HEADER