capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

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