Prefer constexpr to preprocessor macros in FBString.h
[folly.git] / folly / FBString.h
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // @author: Andrei Alexandrescu (aalexandre)
18 // String type.
19
20 #ifndef FOLLY_BASE_FBSTRING_H_
21 #define FOLLY_BASE_FBSTRING_H_
22
23 #include <atomic>
24 #include <limits>
25 #include <type_traits>
26
27 // This file appears in two locations: inside fbcode and in the
28 // libstdc++ source code (when embedding fbstring as std::string).
29 // To aid in this schizophrenic use, _LIBSTDCXX_FBSTRING is defined in
30 // libstdc++'s c++config.h, to gate use inside fbcode v. libstdc++.
31 #ifdef _LIBSTDCXX_FBSTRING
32
33 #pragma GCC system_header
34
35 // Handle the cases where the fbcode version (folly/Malloc.h) is included
36 // either before or after this inclusion.
37 #ifdef FOLLY_MALLOC_H_
38 #undef FOLLY_MALLOC_H_
39 #include "basic_fbstring_malloc.h" // nolint
40 #else
41 #include "basic_fbstring_malloc.h" // nolint
42 #undef FOLLY_MALLOC_H_
43 #endif
44
45 #else // !_LIBSTDCXX_FBSTRING
46
47 #include <folly/Portability.h>
48
49 // libc++ doesn't provide this header, nor does msvc
50 #ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
51 #include <bits/c++config.h>
52 #endif
53
54 #include <string>
55 #include <cstring>
56 #include <cassert>
57 #include <algorithm>
58
59 #include <folly/Traits.h>
60 #include <folly/Malloc.h>
61 #include <folly/Hash.h>
62 #include <folly/ScopeGuard.h>
63
64 #if FOLLY_HAVE_DEPRECATED_ASSOC
65 #ifdef _GLIBCXX_SYMVER
66 #include <ext/hash_set>
67 #include <ext/hash_map>
68 #endif
69 #endif
70
71 #endif
72
73 // We defined these here rather than including Likely.h to avoid
74 // redefinition errors when fbstring is imported into libstdc++.
75 #if defined(__GNUC__) && __GNUC__ >= 4
76 #define FBSTRING_LIKELY(x)   (__builtin_expect((x), 1))
77 #define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0))
78 #else
79 #define FBSTRING_LIKELY(x)   (x)
80 #define FBSTRING_UNLIKELY(x) (x)
81 #endif
82
83 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
84 #pragma GCC diagnostic push
85 #pragma GCC diagnostic ignored "-Wshadow"
86
87 // FBString cannot use throw when replacing std::string, though it may still
88 // use std::__throw_*
89 // nolint
90 #define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW
91
92 #ifdef _LIBSTDCXX_FBSTRING
93 namespace std _GLIBCXX_VISIBILITY(default) {
94 _GLIBCXX_BEGIN_NAMESPACE_VERSION
95 #else
96 namespace folly {
97 #endif
98
99 // Different versions of gcc/clang support different versions of
100 // the address sanitizer attribute.  Unfortunately, this attribute
101 // has issues when inlining is used, so disable that as well.
102 #if defined(__clang__)
103 # if __has_feature(address_sanitizer)
104 #  if __has_attribute(__no_address_safety_analysis__)
105 #   define FBSTRING_DISABLE_ADDRESS_SANITIZER \
106       __attribute__((__no_address_safety_analysis__, __noinline__))
107 #  elif __has_attribute(__no_sanitize_address__)
108 #   define FBSTRING_DISABLE_ADDRESS_SANITIZER \
109       __attribute__((__no_sanitize_address__, __noinline__))
110 #  endif
111 # endif
112 #elif defined (__GNUC__) && \
113       (__GNUC__ == 4) && \
114       (__GNUC_MINOR__ >= 8) && \
115       __SANITIZE_ADDRESS__
116 # define FBSTRING_DISABLE_ADDRESS_SANITIZER \
117     __attribute__((__no_address_safety_analysis__, __noinline__))
118 #endif
119 #ifndef FBSTRING_DISABLE_ADDRESS_SANITIZER
120 # define FBSTRING_DISABLE_ADDRESS_SANITIZER
121 #endif
122
123 namespace fbstring_detail {
124
125 template <class InIt, class OutIt>
126 inline
127 OutIt copy_n(InIt b,
128              typename std::iterator_traits<InIt>::difference_type n,
129              OutIt d) {
130   for (; n != 0; --n, ++b, ++d) {
131     *d = *b;
132   }
133   return d;
134 }
135
136 template <class Pod, class T>
137 inline void pod_fill(Pod* b, Pod* e, T c) {
138   assert(b && e && b <= e);
139   /*static*/ if (sizeof(T) == 1) {
140     memset(b, c, e - b);
141   } else {
142     auto const ee = b + ((e - b) & ~7u);
143     for (; b != ee; b += 8) {
144       b[0] = c;
145       b[1] = c;
146       b[2] = c;
147       b[3] = c;
148       b[4] = c;
149       b[5] = c;
150       b[6] = c;
151       b[7] = c;
152     }
153     // Leftovers
154     for (; b != e; ++b) {
155       *b = c;
156     }
157   }
158 }
159
160 /*
161  * Lightly structured memcpy, simplifies copying PODs and introduces
162  * some asserts. Unfortunately using this function may cause
163  * measurable overhead (presumably because it adjusts from a begin/end
164  * convention to a pointer/size convention, so it does some extra
165  * arithmetic even though the caller might have done the inverse
166  * adaptation outside).
167  */
168 template <class Pod>
169 inline void pod_copy(const Pod* b, const Pod* e, Pod* d) {
170   assert(e >= b);
171   assert(d >= e || d + (e - b) <= b);
172   memcpy(d, b, (e - b) * sizeof(Pod));
173 }
174
175 /*
176  * Lightly structured memmove, simplifies copying PODs and introduces
177  * some asserts
178  */
179 template <class Pod>
180 inline void pod_move(const Pod* b, const Pod* e, Pod* d) {
181   assert(e >= b);
182   memmove(d, b, (e - b) * sizeof(*b));
183 }
184
185 } // namespace fbstring_detail
186
187 /**
188  * Defines a special acquisition method for constructing fbstring
189  * objects. AcquireMallocatedString means that the user passes a
190  * pointer to a malloc-allocated string that the fbstring object will
191  * take into custody.
192  */
193 enum class AcquireMallocatedString {};
194
195 /*
196  * fbstring_core_model is a mock-up type that defines all required
197  * signatures of a fbstring core. The fbstring class itself uses such
198  * a core object to implement all of the numerous member functions
199  * required by the standard.
200  *
201  * If you want to define a new core, copy the definition below and
202  * implement the primitives. Then plug the core into basic_fbstring as
203  * a template argument.
204
205 template <class Char>
206 class fbstring_core_model {
207 public:
208   fbstring_core_model();
209   fbstring_core_model(const fbstring_core_model &);
210   ~fbstring_core_model();
211   // Returns a pointer to string's buffer (currently only contiguous
212   // strings are supported). The pointer is guaranteed to be valid
213   // until the next call to a non-const member function.
214   const Char * data() const;
215   // Much like data(), except the string is prepared to support
216   // character-level changes. This call is a signal for
217   // e.g. reference-counted implementation to fork the data. The
218   // pointer is guaranteed to be valid until the next call to a
219   // non-const member function.
220   Char * mutable_data();
221   // Returns a pointer to string's buffer and guarantees that a
222   // readable '\0' lies right after the buffer. The pointer is
223   // guaranteed to be valid until the next call to a non-const member
224   // function.
225   const Char * c_str() const;
226   // Shrinks the string by delta characters. Asserts that delta <=
227   // size().
228   void shrink(size_t delta);
229   // Expands the string by delta characters (i.e. after this call
230   // size() will report the old size() plus delta) but without
231   // initializing the expanded region. Returns a pointer to the memory
232   // to be initialized (the beginning of the expanded portion). The
233   // caller is expected to fill the expanded area appropriately.
234   Char* expand_noinit(size_t delta);
235   // Expands the string by one character and sets the last character
236   // to c.
237   void push_back(Char c);
238   // Returns the string's size.
239   size_t size() const;
240   // Returns the string's capacity, i.e. maximum size that the string
241   // can grow to without reallocation. Note that for reference counted
242   // strings that's technically a lie - even assigning characters
243   // within the existing size would cause a reallocation.
244   size_t capacity() const;
245   // Returns true if the data underlying the string is actually shared
246   // across multiple strings (in a refcounted fashion).
247   bool isShared() const;
248   // Makes sure that at least minCapacity characters are available for
249   // the string without reallocation. For reference-counted strings,
250   // it should fork the data even if minCapacity < size().
251   void reserve(size_t minCapacity);
252 private:
253   // Do not implement
254   fbstring_core_model& operator=(const fbstring_core_model &);
255 };
256 */
257
258 /**
259  * This is the core of the string. The code should work on 32- and
260  * 64-bit and both big- and little-endianan architectures with any
261  * Char size.
262  *
263  * The storage is selected as follows (assuming we store one-byte
264  * characters on a 64-bit machine): (a) "small" strings between 0 and
265  * 23 chars are stored in-situ without allocation (the rightmost byte
266  * stores the size); (b) "medium" strings from 24 through 254 chars
267  * are stored in malloc-allocated memory that is copied eagerly; (c)
268  * "large" strings of 255 chars and above are stored in a similar
269  * structure as medium arrays, except that the string is
270  * reference-counted and copied lazily. the reference count is
271  * allocated right before the character array.
272  *
273  * The discriminator between these three strategies sits in two
274  * bits of the rightmost char of the storage. If neither is set, then the
275  * string is small (and its length sits in the lower-order bits on
276  * little-endian or the high-order bits on big-endian of that
277  * rightmost character). If the MSb is set, the string is medium width.
278  * If the second MSb is set, then the string is large. On little-endian,
279  * these 2 bits are the 2 MSbs of MediumLarge::capacity_, while on
280  * big-endian, these 2 bits are the 2 LSbs. This keeps both little-endian
281  * and big-endian fbstring_core equivalent with merely different ops used
282  * to extract capacity/category.
283  */
284 template <class Char> class fbstring_core {
285 protected:
286   static constexpr bool kIsLittleEndian =
287     __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
288   static constexpr bool kIsBigEndian =
289     __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
290   static_assert(
291       kIsLittleEndian || kIsBigEndian, "unable to identify endianness");
292 public:
293   fbstring_core() noexcept {
294     // Only initialize the tag, will set the MSBs (i.e. the small
295     // string size) to zero too
296     ml_.capacity_ = kIsLittleEndian
297       ? maxSmallSize << (8 * (sizeof(size_t) - sizeof(Char)))
298       : ml_.capacity_ = maxSmallSize << 2;
299     // or: setSmallSize(0);
300     writeTerminator();
301     assert(category() == Category::isSmall && size() == 0);
302   }
303
304   fbstring_core(const fbstring_core & rhs) {
305     assert(&rhs != this);
306     // Simplest case first: small strings are bitblitted
307     if (rhs.category() == Category::isSmall) {
308       static_assert(offsetof(MediumLarge, data_) == 0,
309           "fbstring layout failure");
310       static_assert(offsetof(MediumLarge, size_) == sizeof(ml_.data_),
311           "fbstring layout failure");
312       static_assert(offsetof(MediumLarge, capacity_) == 2 * sizeof(ml_.data_),
313           "fbstring layout failure");
314       const size_t size = rhs.smallSize();
315       if (size == 0) {
316         ml_.capacity_ = rhs.ml_.capacity_;
317         writeTerminator();
318       } else {
319         // Just write the whole thing, don't look at details. In
320         // particular we need to copy capacity anyway because we want
321         // to set the size (don't forget that the last character,
322         // which stores a short string's length, is shared with the
323         // ml_.capacity field).
324         ml_ = rhs.ml_;
325       }
326       assert(category() == Category::isSmall && this->size() == rhs.size());
327     } else if (rhs.category() == Category::isLarge) {
328       // Large strings are just refcounted
329       ml_ = rhs.ml_;
330       RefCounted::incrementRefs(ml_.data_);
331       assert(category() == Category::isLarge && size() == rhs.size());
332     } else {
333       // Medium strings are copied eagerly. Don't forget to allocate
334       // one extra Char for the null terminator.
335       auto const allocSize =
336            goodMallocSize((1 + rhs.ml_.size_) * sizeof(Char));
337       ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
338       fbstring_detail::pod_copy(rhs.ml_.data_,
339                                 // 1 for terminator
340                                 rhs.ml_.data_ + rhs.ml_.size_ + 1,
341                                 ml_.data_);
342       // No need for writeTerminator() here, we copied one extra
343       // element just above.
344       ml_.size_ = rhs.ml_.size_;
345       ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
346       assert(category() == Category::isMedium);
347     }
348     assert(size() == rhs.size());
349     assert(memcmp(data(), rhs.data(), size() * sizeof(Char)) == 0);
350   }
351
352   fbstring_core(fbstring_core&& goner) noexcept {
353     if (goner.category() == Category::isSmall) {
354       // Just copy, leave the goner in peace
355       new(this) fbstring_core(goner.small_, goner.smallSize());
356     } else {
357       // Take goner's guts
358       ml_ = goner.ml_;
359       // Clean goner's carcass
360       goner.setSmallSize(0);
361     }
362   }
363
364   // NOTE(agallagher): The word-aligned copy path copies bytes which are
365   // outside the range of the string, and makes address sanitizer unhappy,
366   // so just disable it on this function.
367   fbstring_core(const Char *const data, const size_t size)
368       FBSTRING_DISABLE_ADDRESS_SANITIZER {
369 #ifndef NDEBUG
370 #ifndef _LIBSTDCXX_FBSTRING
371     SCOPE_EXIT {
372       assert(this->size() == size);
373       assert(memcmp(this->data(), data, size * sizeof(Char)) == 0);
374     };
375 #endif
376 #endif
377
378     // Simplest case first: small strings are bitblitted
379     if (size <= maxSmallSize) {
380       // Layout is: Char* data_, size_t size_, size_t capacity_
381       static_assert(sizeof(*this) == sizeof(Char*) + 2 * sizeof(size_t),
382           "fbstring has unexpected size");
383       static_assert(sizeof(Char*) == sizeof(size_t),
384           "fbstring size assumption violation");
385       // sizeof(size_t) must be a power of 2
386       static_assert((sizeof(size_t) & (sizeof(size_t) - 1)) == 0,
387           "fbstring size assumption violation");
388
389       // If data is aligned, use fast word-wise copying. Otherwise,
390       // use conservative memcpy.
391       if (reinterpret_cast<size_t>(data) & (sizeof(size_t) - 1)) {
392         fbstring_detail::pod_copy(data, data + size, small_);
393       } else {
394         // Copy one word (64 bits) at a time
395         const size_t byteSize = size * sizeof(Char);
396         if (byteSize > 2 * sizeof(size_t)) {
397           // Copy three words
398           ml_.capacity_ = reinterpret_cast<const size_t*>(data)[2];
399           copyTwo:
400           ml_.size_ = reinterpret_cast<const size_t*>(data)[1];
401           copyOne:
402           ml_.data_ = *reinterpret_cast<Char**>(const_cast<Char*>(data));
403         } else if (byteSize > sizeof(size_t)) {
404           // Copy two words
405           goto copyTwo;
406         } else if (size > 0) {
407           // Copy one word
408           goto copyOne;
409         }
410       }
411       setSmallSize(size);
412       return;
413     } else if (size <= maxMediumSize) {
414       // Medium strings are allocated normally. Don't forget to
415       // allocate one extra Char for the terminating null.
416       auto const allocSize = goodMallocSize((1 + size) * sizeof(Char));
417       ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
418       fbstring_detail::pod_copy(data, data + size, ml_.data_);
419       ml_.size_ = size;
420       ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
421     } else {
422       // Large strings are allocated differently
423       size_t effectiveCapacity = size;
424       auto const newRC = RefCounted::create(data, & effectiveCapacity);
425       ml_.data_ = newRC->data_;
426       ml_.size_ = size;
427       ml_.setCapacity(effectiveCapacity, Category::isLarge);
428     }
429     writeTerminator();
430   }
431
432   ~fbstring_core() noexcept {
433     auto const c = category();
434     if (c == Category::isSmall) {
435       return;
436     }
437     if (c == Category::isMedium) {
438       free(ml_.data_);
439       return;
440     }
441     RefCounted::decrementRefs(ml_.data_);
442   }
443
444   // Snatches a previously mallocated string. The parameter "size"
445   // is the size of the string, and the parameter "allocatedSize"
446   // is the size of the mallocated block.  The string must be
447   // \0-terminated, so allocatedSize >= size + 1 and data[size] == '\0'.
448   //
449   // So if you want a 2-character string, pass malloc(3) as "data",
450   // pass 2 as "size", and pass 3 as "allocatedSize".
451   fbstring_core(Char * const data,
452                 const size_t size,
453                 const size_t allocatedSize,
454                 AcquireMallocatedString) {
455     if (size > 0) {
456       assert(allocatedSize >= size + 1);
457       assert(data[size] == '\0');
458       // Use the medium string storage
459       ml_.data_ = data;
460       ml_.size_ = size;
461       // Don't forget about null terminator
462       ml_.setCapacity(allocatedSize - 1, Category::isMedium);
463     } else {
464       // No need for the memory
465       free(data);
466       setSmallSize(0);
467     }
468   }
469
470   // swap below doesn't test whether &rhs == this (and instead
471   // potentially does extra work) on the premise that the rarity of
472   // that situation actually makes the check more expensive than is
473   // worth.
474   void swap(fbstring_core & rhs) {
475     auto const t = ml_;
476     ml_ = rhs.ml_;
477     rhs.ml_ = t;
478   }
479
480   // In C++11 data() and c_str() are 100% equivalent.
481   const Char * data() const {
482     return c_str();
483   }
484
485   Char * mutable_data() {
486     auto const c = category();
487     if (c == Category::isSmall) {
488       return small_;
489     }
490     assert(c == Category::isMedium || c == Category::isLarge);
491     if (c == Category::isLarge && RefCounted::refs(ml_.data_) > 1) {
492       // Ensure unique.
493       size_t effectiveCapacity = ml_.capacity();
494       auto const newRC = RefCounted::create(& effectiveCapacity);
495       // If this fails, someone placed the wrong capacity in an
496       // fbstring.
497       assert(effectiveCapacity >= ml_.capacity());
498       fbstring_detail::pod_copy(ml_.data_, ml_.data_ + ml_.size_ + 1,
499                                 newRC->data_);
500       RefCounted::decrementRefs(ml_.data_);
501       ml_.data_ = newRC->data_;
502       // No need to call writeTerminator(), we have + 1 above.
503     }
504     return ml_.data_;
505   }
506
507   const Char * c_str() const {
508     auto const c = category();
509     if (c == Category::isSmall) {
510       assert(small_[smallSize()] == '\0');
511       return small_;
512     }
513     assert(c == Category::isMedium || c == Category::isLarge);
514     assert(ml_.data_[ml_.size_] == '\0');
515     return ml_.data_;
516   }
517
518   void shrink(const size_t delta) {
519     if (category() == Category::isSmall) {
520       // Check for underflow
521       assert(delta <= smallSize());
522       setSmallSize(smallSize() - delta);
523     } else if (category() == Category::isMedium ||
524                RefCounted::refs(ml_.data_) == 1) {
525       // Medium strings and unique large strings need no special
526       // handling.
527       assert(ml_.size_ >= delta);
528       ml_.size_ -= delta;
529       writeTerminator();
530     } else {
531       assert(ml_.size_ >= delta);
532       // Shared large string, must make unique. This is because of the
533       // durn terminator must be written, which may trample the shared
534       // data.
535       if (delta) {
536         fbstring_core(ml_.data_, ml_.size_ - delta).swap(*this);
537       }
538       // No need to write the terminator.
539     }
540   }
541
542   void reserve(size_t minCapacity) {
543     if (category() == Category::isLarge) {
544       // Ensure unique
545       if (RefCounted::refs(ml_.data_) > 1) {
546         // We must make it unique regardless; in-place reallocation is
547         // useless if the string is shared. In order to not surprise
548         // people, reserve the new block at current capacity or
549         // more. That way, a string's capacity never shrinks after a
550         // call to reserve.
551         minCapacity = std::max(minCapacity, ml_.capacity());
552         auto const newRC = RefCounted::create(& minCapacity);
553         fbstring_detail::pod_copy(ml_.data_, ml_.data_ + ml_.size_ + 1,
554                                    newRC->data_);
555         // Done with the old data. No need to call writeTerminator(),
556         // we have + 1 above.
557         RefCounted::decrementRefs(ml_.data_);
558         ml_.data_ = newRC->data_;
559         ml_.setCapacity(minCapacity, Category::isLarge);
560         // size remains unchanged
561       } else {
562         // String is not shared, so let's try to realloc (if needed)
563         if (minCapacity > ml_.capacity()) {
564           // Asking for more memory
565           auto const newRC =
566                RefCounted::reallocate(ml_.data_, ml_.size_,
567                                       ml_.capacity(), minCapacity);
568           ml_.data_ = newRC->data_;
569           ml_.setCapacity(minCapacity, Category::isLarge);
570           writeTerminator();
571         }
572         assert(capacity() >= minCapacity);
573       }
574     } else if (category() == Category::isMedium) {
575       // String is not shared
576       if (minCapacity <= ml_.capacity()) {
577         return; // nothing to do, there's enough room
578       }
579       if (minCapacity <= maxMediumSize) {
580         // Keep the string at medium size. Don't forget to allocate
581         // one extra Char for the terminating null.
582         size_t capacityBytes = goodMallocSize((1 + minCapacity) * sizeof(Char));
583         ml_.data_ = static_cast<Char *>(
584           smartRealloc(
585             ml_.data_,
586             ml_.size_ * sizeof(Char),
587             (ml_.capacity() + 1) * sizeof(Char),
588             capacityBytes));
589         writeTerminator();
590         ml_.setCapacity(capacityBytes / sizeof(Char) - 1, Category::isMedium);
591       } else {
592         // Conversion from medium to large string
593         fbstring_core nascent;
594         // Will recurse to another branch of this function
595         nascent.reserve(minCapacity);
596         nascent.ml_.size_ = ml_.size_;
597         fbstring_detail::pod_copy(ml_.data_, ml_.data_ + ml_.size_,
598                                   nascent.ml_.data_);
599         nascent.swap(*this);
600         writeTerminator();
601         assert(capacity() >= minCapacity);
602       }
603     } else {
604       assert(category() == Category::isSmall);
605       if (minCapacity > maxMediumSize) {
606         // large
607         auto const newRC = RefCounted::create(& minCapacity);
608         auto const size = smallSize();
609         fbstring_detail::pod_copy(small_, small_ + size + 1, newRC->data_);
610         // No need for writeTerminator(), we wrote it above with + 1.
611         ml_.data_ = newRC->data_;
612         ml_.size_ = size;
613         ml_.setCapacity(minCapacity, Category::isLarge);
614         assert(capacity() >= minCapacity);
615       } else if (minCapacity > maxSmallSize) {
616         // medium
617         // Don't forget to allocate one extra Char for the terminating null
618         auto const allocSizeBytes =
619           goodMallocSize((1 + minCapacity) * sizeof(Char));
620         auto const data = static_cast<Char*>(checkedMalloc(allocSizeBytes));
621         auto const size = smallSize();
622         fbstring_detail::pod_copy(small_, small_ + size + 1, data);
623         // No need for writeTerminator(), we wrote it above with + 1.
624         ml_.data_ = data;
625         ml_.size_ = size;
626         ml_.setCapacity(allocSizeBytes / sizeof(Char) - 1, Category::isMedium);
627       } else {
628         // small
629         // Nothing to do, everything stays put
630       }
631     }
632     assert(capacity() >= minCapacity);
633   }
634
635   Char * expand_noinit(const size_t delta) {
636     // Strategy is simple: make room, then change size
637     assert(capacity() >= size());
638     size_t sz, newSz;
639     if (category() == Category::isSmall) {
640       sz = smallSize();
641       newSz = sz + delta;
642       if (newSz <= maxSmallSize) {
643         setSmallSize(newSz);
644         return small_ + sz;
645       }
646       reserve(newSz);
647     } else {
648       sz = ml_.size_;
649       newSz = ml_.size_ + delta;
650       if (newSz > capacity()) {
651         reserve(newSz);
652       }
653     }
654     assert(capacity() >= newSz);
655     // Category can't be small - we took care of that above
656     assert(category() == Category::isMedium || category() == Category::isLarge);
657     ml_.size_ = newSz;
658     writeTerminator();
659     assert(size() == newSz);
660     return ml_.data_ + sz;
661   }
662
663   void push_back(Char c) {
664     assert(capacity() >= size());
665     size_t sz;
666     if (category() == Category::isSmall) {
667       sz = smallSize();
668       if (sz < maxSmallSize) {
669         small_[sz] = c;
670         setSmallSize(sz + 1);
671         return;
672       }
673       reserve(maxSmallSize * 2);
674     } else {
675       sz = ml_.size_;
676       if (sz == capacity()) {  // always true for isShared()
677         reserve(1 + sz * 3 / 2);  // ensures not shared
678       }
679     }
680     assert(!isShared());
681     assert(capacity() >= sz + 1);
682     // Category can't be small - we took care of that above
683     assert(category() == Category::isMedium || category() == Category::isLarge);
684     ml_.size_ = sz + 1;
685     ml_.data_[sz] = c;
686     writeTerminator();
687   }
688
689   size_t size() const {
690     return category() == Category::isSmall ? smallSize() : ml_.size_;
691   }
692
693   size_t capacity() const {
694     switch (category()) {
695       case Category::isSmall:
696         return maxSmallSize;
697       case Category::isLarge:
698         // For large-sized strings, a multi-referenced chunk has no
699         // available capacity. This is because any attempt to append
700         // data would trigger a new allocation.
701         if (RefCounted::refs(ml_.data_) > 1) return ml_.size_;
702       default: {}
703     }
704     return ml_.capacity();
705   }
706
707   bool isShared() const {
708     return category() == Category::isLarge && RefCounted::refs(ml_.data_) > 1;
709   }
710
711   void writeTerminator() {
712     if (category() == Category::isSmall) {
713       const auto s = smallSize();
714       if (s != maxSmallSize) {
715         small_[s] = '\0';
716       }
717     } else {
718       ml_.data_[ml_.size_] = '\0';
719     }
720   }
721
722 private:
723   // Disabled
724   fbstring_core & operator=(const fbstring_core & rhs);
725
726   struct RefCounted {
727     std::atomic<size_t> refCount_;
728     Char data_[1];
729
730     static RefCounted * fromData(Char * p) {
731       return static_cast<RefCounted*>(
732         static_cast<void*>(
733           static_cast<unsigned char*>(static_cast<void*>(p))
734           - sizeof(refCount_)));
735     }
736
737     static size_t refs(Char * p) {
738       return fromData(p)->refCount_.load(std::memory_order_acquire);
739     }
740
741     static void incrementRefs(Char * p) {
742       fromData(p)->refCount_.fetch_add(1, std::memory_order_acq_rel);
743     }
744
745     static void decrementRefs(Char * p) {
746       auto const dis = fromData(p);
747       size_t oldcnt = dis->refCount_.fetch_sub(1, std::memory_order_acq_rel);
748       assert(oldcnt > 0);
749       if (oldcnt == 1) {
750         free(dis);
751       }
752     }
753
754     static RefCounted * create(size_t * size) {
755       // Don't forget to allocate one extra Char for the terminating
756       // null. In this case, however, one Char is already part of the
757       // struct.
758       const size_t allocSize = goodMallocSize(
759         sizeof(RefCounted) + *size * sizeof(Char));
760       auto result = static_cast<RefCounted*>(checkedMalloc(allocSize));
761       result->refCount_.store(1, std::memory_order_release);
762       *size = (allocSize - sizeof(RefCounted)) / sizeof(Char);
763       return result;
764     }
765
766     static RefCounted * create(const Char * data, size_t * size) {
767       const size_t effectiveSize = *size;
768       auto result = create(size);
769       fbstring_detail::pod_copy(data, data + effectiveSize, result->data_);
770       return result;
771     }
772
773     static RefCounted * reallocate(Char *const data,
774                                    const size_t currentSize,
775                                    const size_t currentCapacity,
776                                    const size_t newCapacity) {
777       assert(newCapacity > 0 && newCapacity > currentSize);
778       auto const dis = fromData(data);
779       assert(dis->refCount_.load(std::memory_order_acquire) == 1);
780       // Don't forget to allocate one extra Char for the terminating
781       // null. In this case, however, one Char is already part of the
782       // struct.
783       auto result = static_cast<RefCounted*>(
784              smartRealloc(dis,
785                           sizeof(RefCounted) + currentSize * sizeof(Char),
786                           sizeof(RefCounted) + currentCapacity * sizeof(Char),
787                           sizeof(RefCounted) + newCapacity * sizeof(Char)));
788       assert(result->refCount_.load(std::memory_order_acquire) == 1);
789       return result;
790     }
791   };
792
793   typedef std::conditional<sizeof(size_t) == 4, uint32_t, uint64_t>::type
794           category_type;
795
796   enum class Category : category_type {
797     isSmall = 0,
798     isMedium = kIsLittleEndian
799       ? sizeof(size_t) == 4 ? 0x80000000 : 0x8000000000000000
800       : 0x2,
801     isLarge =  kIsLittleEndian
802       ? sizeof(size_t) == 4 ? 0x40000000 : 0x4000000000000000
803       : 0x1,
804   };
805
806   Category category() const {
807     // works for both big-endian and little-endian
808     return static_cast<Category>(ml_.capacity_ & categoryExtractMask);
809   }
810
811   struct MediumLarge {
812     Char * data_;
813     size_t size_;
814     size_t capacity_;
815
816     size_t capacity() const {
817       return kIsLittleEndian
818         ? capacity_ & capacityExtractMask
819         : capacity_ >> 2;
820     }
821
822     void setCapacity(size_t cap, Category cat) {
823         capacity_ = kIsLittleEndian
824           ? cap | static_cast<category_type>(cat)
825           : (cap << 2) | static_cast<category_type>(cat);
826     }
827   };
828
829   union {
830     Char small_[sizeof(MediumLarge) / sizeof(Char)];
831     MediumLarge ml_;
832   };
833
834   enum : size_t {
835     lastChar = sizeof(MediumLarge) - 1,
836     maxSmallSize = lastChar / sizeof(Char),
837     maxMediumSize = 254 / sizeof(Char),            // coincides with the small
838                                                    // bin size in dlmalloc
839     categoryExtractMask = kIsLittleEndian
840       ? sizeof(size_t) == 4 ? 0xC0000000 : 0xC000000000000000
841       : 0x3,
842     capacityExtractMask = kIsLittleEndian
843       ? ~categoryExtractMask
844       : 0x0 /*unused*/,
845   };
846   static_assert(!(sizeof(MediumLarge) % sizeof(Char)),
847                 "Corrupt memory layout for fbstring.");
848
849   size_t smallSize() const {
850     assert(category() == Category::isSmall);
851     auto shift = kIsLittleEndian ? 0 : 2;
852     auto smallShifted = static_cast<size_t>(small_[maxSmallSize]) >> shift;
853     assert(static_cast<size_t>(maxSmallSize) >= smallShifted);
854     return static_cast<size_t>(maxSmallSize) - smallShifted;
855   }
856
857   void setSmallSize(size_t s) {
858     // Warning: this should work with uninitialized strings too,
859     // so don't assume anything about the previous value of
860     // small_[maxSmallSize].
861     assert(s <= maxSmallSize);
862     small_[maxSmallSize] = kIsLittleEndian
863       ? maxSmallSize - s
864       : (maxSmallSize - s) << 2;
865     writeTerminator();
866   }
867 };
868
869 #ifndef _LIBSTDCXX_FBSTRING
870 /**
871  * Dummy fbstring core that uses an actual std::string. This doesn't
872  * make any sense - it's just for testing purposes.
873  */
874 template <class Char>
875 class dummy_fbstring_core {
876 public:
877   dummy_fbstring_core() {
878   }
879   dummy_fbstring_core(const dummy_fbstring_core& another)
880       : backend_(another.backend_) {
881   }
882   dummy_fbstring_core(const Char * s, size_t n)
883       : backend_(s, n) {
884   }
885   void swap(dummy_fbstring_core & rhs) {
886     backend_.swap(rhs.backend_);
887   }
888   const Char * data() const {
889     return backend_.data();
890   }
891   Char * mutable_data() {
892     //assert(!backend_.empty());
893     return &*backend_.begin();
894   }
895   void shrink(size_t delta) {
896     assert(delta <= size());
897     backend_.resize(size() - delta);
898   }
899   Char * expand_noinit(size_t delta) {
900     auto const sz = size();
901     backend_.resize(size() + delta);
902     return backend_.data() + sz;
903   }
904   void push_back(Char c) {
905     backend_.push_back(c);
906   }
907   size_t size() const {
908     return backend_.size();
909   }
910   size_t capacity() const {
911     return backend_.capacity();
912   }
913   bool isShared() const {
914     return false;
915   }
916   void reserve(size_t minCapacity) {
917     backend_.reserve(minCapacity);
918   }
919
920 private:
921   std::basic_string<Char> backend_;
922 };
923 #endif // !_LIBSTDCXX_FBSTRING
924
925 /**
926  * This is the basic_string replacement. For conformity,
927  * basic_fbstring takes the same template parameters, plus the last
928  * one which is the core.
929  */
930 #ifdef _LIBSTDCXX_FBSTRING
931 template <typename E, class T, class A, class Storage>
932 #else
933 template <typename E,
934           class T = std::char_traits<E>,
935           class A = std::allocator<E>,
936           class Storage = fbstring_core<E> >
937 #endif
938 class basic_fbstring {
939
940   static void enforce(
941       bool condition,
942       void (*throw_exc)(const char*),
943       const char* msg) {
944     if (!condition) throw_exc(msg);
945   }
946
947   bool isSane() const {
948     return
949       begin() <= end() &&
950       empty() == (size() == 0) &&
951       empty() == (begin() == end()) &&
952       size() <= max_size() &&
953       capacity() <= max_size() &&
954       size() <= capacity() &&
955       begin()[size()] == '\0';
956   }
957
958   struct Invariant;
959   friend struct Invariant;
960   struct Invariant {
961 #ifndef NDEBUG
962     explicit Invariant(const basic_fbstring& s) : s_(s) {
963       assert(s_.isSane());
964     }
965     ~Invariant() {
966       assert(s_.isSane());
967     }
968   private:
969     const basic_fbstring& s_;
970 #else
971     explicit Invariant(const basic_fbstring&) {}
972 #endif
973     Invariant& operator=(const Invariant&);
974   };
975
976 public:
977   // types
978   typedef T traits_type;
979   typedef typename traits_type::char_type value_type;
980   typedef A allocator_type;
981   typedef typename A::size_type size_type;
982   typedef typename A::difference_type difference_type;
983
984   typedef typename A::reference reference;
985   typedef typename A::const_reference const_reference;
986   typedef typename A::pointer pointer;
987   typedef typename A::const_pointer const_pointer;
988
989   typedef E* iterator;
990   typedef const E* const_iterator;
991   typedef std::reverse_iterator<iterator
992 #ifdef NO_ITERATOR_TRAITS
993                                 , value_type
994 #endif
995                                 > reverse_iterator;
996   typedef std::reverse_iterator<const_iterator
997 #ifdef NO_ITERATOR_TRAITS
998                                 , const value_type
999 #endif
1000                                 > const_reverse_iterator;
1001
1002   static const size_type npos;                     // = size_type(-1)
1003
1004 private:
1005   static void procrustes(size_type& n, size_type nmax) {
1006     if (n > nmax) n = nmax;
1007   }
1008
1009 public:
1010   // C++11 21.4.2 construct/copy/destroy
1011   explicit basic_fbstring(const A& /*a*/ = A()) noexcept {
1012   }
1013
1014   basic_fbstring(const basic_fbstring& str)
1015       : store_(str.store_) {
1016   }
1017
1018   // Move constructor
1019   basic_fbstring(basic_fbstring&& goner) noexcept
1020       : store_(std::move(goner.store_)) {
1021   }
1022
1023 #ifndef _LIBSTDCXX_FBSTRING
1024   // This is defined for compatibility with std::string
1025   /* implicit */ basic_fbstring(const std::string& str)
1026       : store_(str.data(), str.size()) {
1027   }
1028 #endif
1029
1030   basic_fbstring(const basic_fbstring& str, size_type pos,
1031                  size_type n = npos, const A& a = A()) {
1032     assign(str, pos, n);
1033   }
1034
1035   /* implicit */ basic_fbstring(const value_type* s, const A& /*a*/ = A())
1036       : store_(s, s
1037           ? traits_type::length(s)
1038           : (std::__throw_logic_error(
1039                 "basic_fbstring: null pointer initializer not valid"),
1040              0)) {
1041   }
1042
1043   basic_fbstring(const value_type* s, size_type n, const A& /*a*/ = A())
1044       : store_(s, n) {
1045   }
1046
1047   basic_fbstring(size_type n, value_type c, const A& /*a*/ = A()) {
1048     auto const data = store_.expand_noinit(n);
1049     fbstring_detail::pod_fill(data, data + n, c);
1050     store_.writeTerminator();
1051   }
1052
1053   template <class InIt>
1054   basic_fbstring(InIt begin, InIt end,
1055                  typename std::enable_if<
1056                  !std::is_same<typename std::remove_const<InIt>::type,
1057                  value_type*>::value, const A>::type & /*a*/ = A()) {
1058     assign(begin, end);
1059   }
1060
1061   // Specialization for const char*, const char*
1062   basic_fbstring(const value_type* b, const value_type* e)
1063       : store_(b, e - b) {
1064   }
1065
1066   // Nonstandard constructor
1067   basic_fbstring(value_type *s, size_type n, size_type c,
1068                  AcquireMallocatedString a)
1069       : store_(s, n, c, a) {
1070   }
1071
1072   // Construction from initialization list
1073   basic_fbstring(std::initializer_list<value_type> il) {
1074     assign(il.begin(), il.end());
1075   }
1076
1077   ~basic_fbstring() noexcept {
1078   }
1079
1080   basic_fbstring& operator=(const basic_fbstring& lhs) {
1081     if (FBSTRING_UNLIKELY(&lhs == this)) {
1082       return *this;
1083     }
1084     auto const oldSize = size();
1085     auto const srcSize = lhs.size();
1086     if (capacity() >= srcSize && !store_.isShared()) {
1087       // great, just copy the contents
1088       if (oldSize < srcSize)
1089         store_.expand_noinit(srcSize - oldSize);
1090       else
1091         store_.shrink(oldSize - srcSize);
1092       assert(size() == srcSize);
1093       fbstring_detail::pod_copy(lhs.begin(), lhs.end(), begin());
1094       store_.writeTerminator();
1095     } else {
1096       // need to reallocate, so we may as well create a brand new string
1097       basic_fbstring(lhs).swap(*this);
1098     }
1099     return *this;
1100   }
1101
1102   // Move assignment
1103   basic_fbstring& operator=(basic_fbstring&& goner) noexcept {
1104     if (FBSTRING_UNLIKELY(&goner == this)) {
1105       // Compatibility with std::basic_string<>,
1106       // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support.
1107       return *this;
1108     }
1109     // No need of this anymore
1110     this->~basic_fbstring();
1111     // Move the goner into this
1112     new(&store_) fbstring_core<E>(std::move(goner.store_));
1113     return *this;
1114   }
1115
1116 #ifndef _LIBSTDCXX_FBSTRING
1117   // Compatibility with std::string
1118   basic_fbstring & operator=(const std::string & rhs) {
1119     return assign(rhs.data(), rhs.size());
1120   }
1121
1122   // Compatibility with std::string
1123   std::string toStdString() const {
1124     return std::string(data(), size());
1125   }
1126 #else
1127   // A lot of code in fbcode still uses this method, so keep it here for now.
1128   const basic_fbstring& toStdString() const {
1129     return *this;
1130   }
1131 #endif
1132
1133   basic_fbstring& operator=(const value_type* s) {
1134     return assign(s);
1135   }
1136
1137   basic_fbstring& operator=(value_type c) {
1138     if (empty()) {
1139       store_.expand_noinit(1);
1140     } else if (store_.isShared()) {
1141       basic_fbstring(1, c).swap(*this);
1142       return *this;
1143     } else {
1144       store_.shrink(size() - 1);
1145     }
1146     *store_.mutable_data() = c;
1147     store_.writeTerminator();
1148     return *this;
1149   }
1150
1151   basic_fbstring& operator=(std::initializer_list<value_type> il) {
1152     return assign(il.begin(), il.end());
1153   }
1154
1155   // C++11 21.4.3 iterators:
1156   iterator begin() { return store_.mutable_data(); }
1157
1158   const_iterator begin() const { return store_.data(); }
1159
1160   const_iterator cbegin() const { return begin(); }
1161
1162   iterator end() {
1163     return store_.mutable_data() + store_.size();
1164   }
1165
1166   const_iterator end() const {
1167     return store_.data() + store_.size();
1168   }
1169
1170   const_iterator cend() const { return end(); }
1171
1172   reverse_iterator rbegin() {
1173     return reverse_iterator(end());
1174   }
1175
1176   const_reverse_iterator rbegin() const {
1177     return const_reverse_iterator(end());
1178   }
1179
1180   const_reverse_iterator crbegin() const { return rbegin(); }
1181
1182   reverse_iterator rend() {
1183     return reverse_iterator(begin());
1184   }
1185
1186   const_reverse_iterator rend() const {
1187     return const_reverse_iterator(begin());
1188   }
1189
1190   const_reverse_iterator crend() const { return rend(); }
1191
1192   // Added by C++11
1193   // C++11 21.4.5, element access:
1194   const value_type& front() const { return *begin(); }
1195   const value_type& back() const {
1196     assert(!empty());
1197     // Should be begin()[size() - 1], but that branches twice
1198     return *(end() - 1);
1199   }
1200   value_type& front() { return *begin(); }
1201   value_type& back() {
1202     assert(!empty());
1203     // Should be begin()[size() - 1], but that branches twice
1204     return *(end() - 1);
1205   }
1206   void pop_back() {
1207     assert(!empty());
1208     store_.shrink(1);
1209   }
1210
1211   // C++11 21.4.4 capacity:
1212   size_type size() const { return store_.size(); }
1213
1214   size_type length() const { return size(); }
1215
1216   size_type max_size() const {
1217     return std::numeric_limits<size_type>::max();
1218   }
1219
1220   void resize(const size_type n, const value_type c = value_type()) {
1221     auto size = this->size();
1222     if (n <= size) {
1223       store_.shrink(size - n);
1224     } else {
1225       // Do this in two steps to minimize slack memory copied (see
1226       // smartRealloc).
1227       auto const capacity = this->capacity();
1228       assert(capacity >= size);
1229       if (size < capacity) {
1230         auto delta = std::min(n, capacity) - size;
1231         store_.expand_noinit(delta);
1232         fbstring_detail::pod_fill(begin() + size, end(), c);
1233         size += delta;
1234         if (size == n) {
1235           store_.writeTerminator();
1236           return;
1237         }
1238         assert(size < n);
1239       }
1240       auto const delta = n - size;
1241       store_.expand_noinit(delta);
1242       fbstring_detail::pod_fill(end() - delta, end(), c);
1243       store_.writeTerminator();
1244     }
1245     assert(this->size() == n);
1246   }
1247
1248   size_type capacity() const { return store_.capacity(); }
1249
1250   void reserve(size_type res_arg = 0) {
1251     enforce(res_arg <= max_size(), std::__throw_length_error, "");
1252     store_.reserve(res_arg);
1253   }
1254
1255   void shrink_to_fit() {
1256     // Shrink only if slack memory is sufficiently large
1257     if (capacity() < size() * 3 / 2) {
1258       return;
1259     }
1260     basic_fbstring(cbegin(), cend()).swap(*this);
1261   }
1262
1263   void clear() { resize(0); }
1264
1265   bool empty() const { return size() == 0; }
1266
1267   // C++11 21.4.5 element access:
1268   const_reference operator[](size_type pos) const {
1269     return *(begin() + pos);
1270   }
1271
1272   reference operator[](size_type pos) {
1273     return *(begin() + pos);
1274   }
1275
1276   const_reference at(size_type n) const {
1277     enforce(n <= size(), std::__throw_out_of_range, "");
1278     return (*this)[n];
1279   }
1280
1281   reference at(size_type n) {
1282     enforce(n < size(), std::__throw_out_of_range, "");
1283     return (*this)[n];
1284   }
1285
1286   // C++11 21.4.6 modifiers:
1287   basic_fbstring& operator+=(const basic_fbstring& str) {
1288     return append(str);
1289   }
1290
1291   basic_fbstring& operator+=(const value_type* s) {
1292     return append(s);
1293   }
1294
1295   basic_fbstring& operator+=(const value_type c) {
1296     push_back(c);
1297     return *this;
1298   }
1299
1300   basic_fbstring& operator+=(std::initializer_list<value_type> il) {
1301     append(il);
1302     return *this;
1303   }
1304
1305   basic_fbstring& append(const basic_fbstring& str) {
1306 #ifndef NDEBUG
1307     auto desiredSize = size() + str.size();
1308 #endif
1309     append(str.data(), str.size());
1310     assert(size() == desiredSize);
1311     return *this;
1312   }
1313
1314   basic_fbstring& append(const basic_fbstring& str, const size_type pos,
1315                          size_type n) {
1316     const size_type sz = str.size();
1317     enforce(pos <= sz, std::__throw_out_of_range, "");
1318     procrustes(n, sz - pos);
1319     return append(str.data() + pos, n);
1320   }
1321
1322   basic_fbstring& append(const value_type* s, size_type n) {
1323 #ifndef NDEBUG
1324     Invariant checker(*this);
1325     (void) checker;
1326 #endif
1327     if (FBSTRING_UNLIKELY(!n)) {
1328       // Unlikely but must be done
1329       return *this;
1330     }
1331     auto const oldSize = size();
1332     auto const oldData = data();
1333     // Check for aliasing (rare). We could use "<=" here but in theory
1334     // those do not work for pointers unless the pointers point to
1335     // elements in the same array. For that reason we use
1336     // std::less_equal, which is guaranteed to offer a total order
1337     // over pointers. See discussion at http://goo.gl/Cy2ya for more
1338     // info.
1339     std::less_equal<const value_type*> le;
1340     if (FBSTRING_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) {
1341       assert(le(s + n, oldData + oldSize));
1342       const size_type offset = s - oldData;
1343       store_.reserve(oldSize + n);
1344       // Restore the source
1345       s = data() + offset;
1346     }
1347     // Warning! Repeated appends with short strings may actually incur
1348     // practically quadratic performance. Avoid that by pushing back
1349     // the first character (which ensures exponential growth) and then
1350     // appending the rest normally. Worst case the append may incur a
1351     // second allocation but that will be rare.
1352     push_back(*s++);
1353     --n;
1354     memcpy(store_.expand_noinit(n), s, n * sizeof(value_type));
1355     assert(size() == oldSize + n + 1);
1356     return *this;
1357   }
1358
1359   basic_fbstring& append(const value_type* s) {
1360     return append(s, traits_type::length(s));
1361   }
1362
1363   basic_fbstring& append(size_type n, value_type c) {
1364     resize(size() + n, c);
1365     return *this;
1366   }
1367
1368   template<class InputIterator>
1369   basic_fbstring& append(InputIterator first, InputIterator last) {
1370     insert(end(), first, last);
1371     return *this;
1372   }
1373
1374   basic_fbstring& append(std::initializer_list<value_type> il) {
1375     return append(il.begin(), il.end());
1376   }
1377
1378   void push_back(const value_type c) {             // primitive
1379     store_.push_back(c);
1380   }
1381
1382   basic_fbstring& assign(const basic_fbstring& str) {
1383     if (&str == this) return *this;
1384     return assign(str.data(), str.size());
1385   }
1386
1387   basic_fbstring& assign(basic_fbstring&& str) {
1388     return *this = std::move(str);
1389   }
1390
1391   basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
1392                          size_type n) {
1393     const size_type sz = str.size();
1394     enforce(pos <= sz, std::__throw_out_of_range, "");
1395     procrustes(n, sz - pos);
1396     return assign(str.data() + pos, n);
1397   }
1398
1399   basic_fbstring& assign(const value_type* s, const size_type n) {
1400     Invariant checker(*this);
1401     (void) checker;
1402     if (size() >= n) {
1403       std::copy(s, s + n, begin());
1404       resize(n);
1405       assert(size() == n);
1406     } else {
1407       const value_type *const s2 = s + size();
1408       std::copy(s, s2, begin());
1409       append(s2, n - size());
1410       assert(size() == n);
1411     }
1412     store_.writeTerminator();
1413     assert(size() == n);
1414     return *this;
1415   }
1416
1417   basic_fbstring& assign(const value_type* s) {
1418     return assign(s, traits_type::length(s));
1419   }
1420
1421   basic_fbstring& assign(std::initializer_list<value_type> il) {
1422     return assign(il.begin(), il.end());
1423   }
1424
1425   template <class ItOrLength, class ItOrChar>
1426   basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) {
1427     return replace(begin(), end(), first_or_n, last_or_c);
1428   }
1429
1430   basic_fbstring& insert(size_type pos1, const basic_fbstring& str) {
1431     return insert(pos1, str.data(), str.size());
1432   }
1433
1434   basic_fbstring& insert(size_type pos1, const basic_fbstring& str,
1435                          size_type pos2, size_type n) {
1436     enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
1437     procrustes(n, str.length() - pos2);
1438     return insert(pos1, str.data() + pos2, n);
1439   }
1440
1441   basic_fbstring& insert(size_type pos, const value_type* s, size_type n) {
1442     enforce(pos <= length(), std::__throw_out_of_range, "");
1443     insert(begin() + pos, s, s + n);
1444     return *this;
1445   }
1446
1447   basic_fbstring& insert(size_type pos, const value_type* s) {
1448     return insert(pos, s, traits_type::length(s));
1449   }
1450
1451   basic_fbstring& insert(size_type pos, size_type n, value_type c) {
1452     enforce(pos <= length(), std::__throw_out_of_range, "");
1453     insert(begin() + pos, n, c);
1454     return *this;
1455   }
1456
1457   iterator insert(const_iterator p, const value_type c) {
1458     const size_type pos = p - begin();
1459     insert(p, 1, c);
1460     return begin() + pos;
1461   }
1462
1463 private:
1464   template <int i> class Selector {};
1465
1466   iterator insertImplDiscr(const_iterator p,
1467                            size_type n, value_type c, Selector<1>) {
1468     Invariant checker(*this);
1469     (void) checker;
1470     auto const pos = p - begin();
1471     assert(p >= begin() && p <= end());
1472     if (capacity() - size() < n) {
1473       const size_type sz = p - begin();
1474       reserve(size() + n);
1475       p = begin() + sz;
1476     }
1477     const iterator oldEnd = end();
1478     if (n < size_type(oldEnd - p)) {
1479       append(oldEnd - n, oldEnd);
1480       //std::copy(
1481       //    reverse_iterator(oldEnd - n),
1482       //    reverse_iterator(p),
1483       //    reverse_iterator(oldEnd));
1484       fbstring_detail::pod_move(&*p, &*oldEnd - n,
1485                                 begin() + pos + n);
1486       std::fill(begin() + pos, begin() + pos + n, c);
1487     } else {
1488       append(n - (end() - p), c);
1489       append(iterator(p), oldEnd);
1490       std::fill(iterator(p), oldEnd, c);
1491     }
1492     store_.writeTerminator();
1493     return begin() + pos;
1494   }
1495
1496   template<class InputIter>
1497   iterator insertImplDiscr(const_iterator i,
1498                            InputIter b, InputIter e, Selector<0>) {
1499     return insertImpl(i, b, e,
1500                typename std::iterator_traits<InputIter>::iterator_category());
1501   }
1502
1503   template <class FwdIterator>
1504   iterator insertImpl(const_iterator i,
1505                   FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
1506     Invariant checker(*this);
1507     (void) checker;
1508     const size_type pos = i - begin();
1509     const typename std::iterator_traits<FwdIterator>::difference_type n2 =
1510       std::distance(s1, s2);
1511     assert(n2 >= 0);
1512     using namespace fbstring_detail;
1513     assert(pos <= size());
1514
1515     const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
1516       capacity() - size();
1517     if (maxn2 < n2) {
1518       // realloc the string
1519       reserve(size() + n2);
1520       i = begin() + pos;
1521     }
1522     if (pos + n2 <= size()) {
1523       const iterator tailBegin = end() - n2;
1524       store_.expand_noinit(n2);
1525       fbstring_detail::pod_copy(tailBegin, tailBegin + n2, end() - n2);
1526       std::copy(const_reverse_iterator(tailBegin), const_reverse_iterator(i),
1527                 reverse_iterator(tailBegin + n2));
1528       std::copy(s1, s2, begin() + pos);
1529     } else {
1530       FwdIterator t = s1;
1531       const size_type old_size = size();
1532       std::advance(t, old_size - pos);
1533       const size_t newElems = std::distance(t, s2);
1534       store_.expand_noinit(n2);
1535       std::copy(t, s2, begin() + old_size);
1536       fbstring_detail::pod_copy(data() + pos, data() + old_size,
1537                                  begin() + old_size + newElems);
1538       std::copy(s1, t, begin() + pos);
1539     }
1540     store_.writeTerminator();
1541     return begin() + pos;
1542   }
1543
1544   template <class InputIterator>
1545   iterator insertImpl(const_iterator i,
1546                       InputIterator b, InputIterator e,
1547                       std::input_iterator_tag) {
1548     const auto pos = i - begin();
1549     basic_fbstring temp(begin(), i);
1550     for (; b != e; ++b) {
1551       temp.push_back(*b);
1552     }
1553     temp.append(i, cend());
1554     swap(temp);
1555     return begin() + pos;
1556   }
1557
1558 public:
1559   template <class ItOrLength, class ItOrChar>
1560   iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
1561     Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
1562     return insertImplDiscr(p, first_or_n, last_or_c, sel);
1563   }
1564
1565   iterator insert(const_iterator p, std::initializer_list<value_type> il) {
1566     return insert(p, il.begin(), il.end());
1567   }
1568
1569   basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
1570     Invariant checker(*this);
1571     (void) checker;
1572     enforce(pos <= length(), std::__throw_out_of_range, "");
1573     procrustes(n, length() - pos);
1574     std::copy(begin() + pos + n, end(), begin() + pos);
1575     resize(length() - n);
1576     return *this;
1577   }
1578
1579   iterator erase(iterator position) {
1580     const size_type pos(position - begin());
1581     enforce(pos <= size(), std::__throw_out_of_range, "");
1582     erase(pos, 1);
1583     return begin() + pos;
1584   }
1585
1586   iterator erase(iterator first, iterator last) {
1587     const size_type pos(first - begin());
1588     erase(pos, last - first);
1589     return begin() + pos;
1590   }
1591
1592   // Replaces at most n1 chars of *this, starting with pos1 with the
1593   // content of str
1594   basic_fbstring& replace(size_type pos1, size_type n1,
1595                           const basic_fbstring& str) {
1596     return replace(pos1, n1, str.data(), str.size());
1597   }
1598
1599   // Replaces at most n1 chars of *this, starting with pos1,
1600   // with at most n2 chars of str starting with pos2
1601   basic_fbstring& replace(size_type pos1, size_type n1,
1602                           const basic_fbstring& str,
1603                           size_type pos2, size_type n2) {
1604     enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
1605     return replace(pos1, n1, str.data() + pos2,
1606                    std::min(n2, str.size() - pos2));
1607   }
1608
1609   // Replaces at most n1 chars of *this, starting with pos, with chars from s
1610   basic_fbstring& replace(size_type pos, size_type n1, const value_type* s) {
1611     return replace(pos, n1, s, traits_type::length(s));
1612   }
1613
1614   // Replaces at most n1 chars of *this, starting with pos, with n2
1615   // occurrences of c
1616   //
1617   // consolidated with
1618   //
1619   // Replaces at most n1 chars of *this, starting with pos, with at
1620   // most n2 chars of str.  str must have at least n2 chars.
1621   template <class StrOrLength, class NumOrChar>
1622   basic_fbstring& replace(size_type pos, size_type n1,
1623                           StrOrLength s_or_n2, NumOrChar n_or_c) {
1624     Invariant checker(*this);
1625     (void) checker;
1626     enforce(pos <= size(), std::__throw_out_of_range, "");
1627     procrustes(n1, length() - pos);
1628     const iterator b = begin() + pos;
1629     return replace(b, b + n1, s_or_n2, n_or_c);
1630   }
1631
1632   basic_fbstring& replace(iterator i1, iterator i2, const basic_fbstring& str) {
1633     return replace(i1, i2, str.data(), str.length());
1634   }
1635
1636   basic_fbstring& replace(iterator i1, iterator i2, const value_type* s) {
1637     return replace(i1, i2, s, traits_type::length(s));
1638   }
1639
1640 private:
1641   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1642                                    const value_type* s, size_type n,
1643                                    Selector<2>) {
1644     assert(i1 <= i2);
1645     assert(begin() <= i1 && i1 <= end());
1646     assert(begin() <= i2 && i2 <= end());
1647     return replace(i1, i2, s, s + n);
1648   }
1649
1650   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1651                                    size_type n2, value_type c, Selector<1>) {
1652     const size_type n1 = i2 - i1;
1653     if (n1 > n2) {
1654       std::fill(i1, i1 + n2, c);
1655       erase(i1 + n2, i2);
1656     } else {
1657       std::fill(i1, i2, c);
1658       insert(i2, n2 - n1, c);
1659     }
1660     assert(isSane());
1661     return *this;
1662   }
1663
1664   template <class InputIter>
1665   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1666                                    InputIter b, InputIter e,
1667                                    Selector<0>) {
1668     replaceImpl(i1, i2, b, e,
1669                 typename std::iterator_traits<InputIter>::iterator_category());
1670     return *this;
1671   }
1672
1673 private:
1674   template <class FwdIterator>
1675   bool replaceAliased(iterator i1, iterator i2,
1676                       FwdIterator s1, FwdIterator s2, std::false_type) {
1677     return false;
1678   }
1679
1680   template <class FwdIterator>
1681   bool replaceAliased(iterator i1, iterator i2,
1682                       FwdIterator s1, FwdIterator s2, std::true_type) {
1683     static const std::less_equal<const value_type*> le =
1684       std::less_equal<const value_type*>();
1685     const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
1686     if (!aliased) {
1687       return false;
1688     }
1689     // Aliased replace, copy to new string
1690     basic_fbstring temp;
1691     temp.reserve(size() - (i2 - i1) + std::distance(s1, s2));
1692     temp.append(begin(), i1).append(s1, s2).append(i2, end());
1693     swap(temp);
1694     return true;
1695   }
1696
1697   template <class FwdIterator>
1698   void replaceImpl(iterator i1, iterator i2,
1699                    FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
1700     Invariant checker(*this);
1701     (void) checker;
1702
1703     // Handle aliased replace
1704     if (replaceAliased(i1, i2, s1, s2,
1705           std::integral_constant<bool,
1706             std::is_same<FwdIterator, iterator>::value ||
1707             std::is_same<FwdIterator, const_iterator>::value>())) {
1708       return;
1709     }
1710
1711     auto const n1 = i2 - i1;
1712     assert(n1 >= 0);
1713     auto const n2 = std::distance(s1, s2);
1714     assert(n2 >= 0);
1715
1716     if (n1 > n2) {
1717       // shrinks
1718       std::copy(s1, s2, i1);
1719       erase(i1 + n2, i2);
1720     } else {
1721       // grows
1722       fbstring_detail::copy_n(s1, n1, i1);
1723       std::advance(s1, n1);
1724       insert(i2, s1, s2);
1725     }
1726     assert(isSane());
1727   }
1728
1729   template <class InputIterator>
1730   void replaceImpl(iterator i1, iterator i2,
1731                    InputIterator b, InputIterator e, std::input_iterator_tag) {
1732     basic_fbstring temp(begin(), i1);
1733     temp.append(b, e).append(i2, end());
1734     swap(temp);
1735   }
1736
1737 public:
1738   template <class T1, class T2>
1739   basic_fbstring& replace(iterator i1, iterator i2,
1740                           T1 first_or_n_or_s, T2 last_or_c_or_n) {
1741     const bool
1742       num1 = std::numeric_limits<T1>::is_specialized,
1743       num2 = std::numeric_limits<T2>::is_specialized;
1744     return replaceImplDiscr(
1745       i1, i2, first_or_n_or_s, last_or_c_or_n,
1746       Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
1747   }
1748
1749   size_type copy(value_type* s, size_type n, size_type pos = 0) const {
1750     enforce(pos <= size(), std::__throw_out_of_range, "");
1751     procrustes(n, size() - pos);
1752
1753     fbstring_detail::pod_copy(
1754       data() + pos,
1755       data() + pos + n,
1756       s);
1757     return n;
1758   }
1759
1760   void swap(basic_fbstring& rhs) {
1761     store_.swap(rhs.store_);
1762   }
1763
1764   const value_type* c_str() const {
1765     return store_.c_str();
1766   }
1767
1768   const value_type* data() const { return c_str(); }
1769
1770   allocator_type get_allocator() const {
1771     return allocator_type();
1772   }
1773
1774   size_type find(const basic_fbstring& str, size_type pos = 0) const {
1775     return find(str.data(), pos, str.length());
1776   }
1777
1778   size_type find(const value_type* needle, const size_type pos,
1779                  const size_type nsize) const {
1780     if (!nsize) return pos;
1781     auto const size = this->size();
1782     // nsize + pos can overflow (eg pos == npos), guard against that by checking
1783     // that nsize + pos does not wrap around.
1784     if (nsize + pos > size || nsize + pos < pos) return npos;
1785     // Don't use std::search, use a Boyer-Moore-like trick by comparing
1786     // the last characters first
1787     auto const haystack = data();
1788     auto const nsize_1 = nsize - 1;
1789     auto const lastNeedle = needle[nsize_1];
1790
1791     // Boyer-Moore skip value for the last char in the needle. Zero is
1792     // not a valid value; skip will be computed the first time it's
1793     // needed.
1794     size_type skip = 0;
1795
1796     const E * i = haystack + pos;
1797     auto iEnd = haystack + size - nsize_1;
1798
1799     while (i < iEnd) {
1800       // Boyer-Moore: match the last element in the needle
1801       while (i[nsize_1] != lastNeedle) {
1802         if (++i == iEnd) {
1803           // not found
1804           return npos;
1805         }
1806       }
1807       // Here we know that the last char matches
1808       // Continue in pedestrian mode
1809       for (size_t j = 0; ; ) {
1810         assert(j < nsize);
1811         if (i[j] != needle[j]) {
1812           // Not found, we can skip
1813           // Compute the skip value lazily
1814           if (skip == 0) {
1815             skip = 1;
1816             while (skip <= nsize_1 && needle[nsize_1 - skip] != lastNeedle) {
1817               ++skip;
1818             }
1819           }
1820           i += skip;
1821           break;
1822         }
1823         // Check if done searching
1824         if (++j == nsize) {
1825           // Yay
1826           return i - haystack;
1827         }
1828       }
1829     }
1830     return npos;
1831   }
1832
1833   size_type find(const value_type* s, size_type pos = 0) const {
1834     return find(s, pos, traits_type::length(s));
1835   }
1836
1837   size_type find (value_type c, size_type pos = 0) const {
1838     return find(&c, pos, 1);
1839   }
1840
1841   size_type rfind(const basic_fbstring& str, size_type pos = npos) const {
1842     return rfind(str.data(), pos, str.length());
1843   }
1844
1845   size_type rfind(const value_type* s, size_type pos, size_type n) const {
1846     if (n > length()) return npos;
1847     pos = std::min(pos, length() - n);
1848     if (n == 0) return pos;
1849
1850     const_iterator i(begin() + pos);
1851     for (; ; --i) {
1852       if (traits_type::eq(*i, *s)
1853           && traits_type::compare(&*i, s, n) == 0) {
1854         return i - begin();
1855       }
1856       if (i == begin()) break;
1857     }
1858     return npos;
1859   }
1860
1861   size_type rfind(const value_type* s, size_type pos = npos) const {
1862     return rfind(s, pos, traits_type::length(s));
1863   }
1864
1865   size_type rfind(value_type c, size_type pos = npos) const {
1866     return rfind(&c, pos, 1);
1867   }
1868
1869   size_type find_first_of(const basic_fbstring& str, size_type pos = 0) const {
1870     return find_first_of(str.data(), pos, str.length());
1871   }
1872
1873   size_type find_first_of(const value_type* s,
1874                           size_type pos, size_type n) const {
1875     if (pos > length() || n == 0) return npos;
1876     const_iterator i(begin() + pos),
1877       finish(end());
1878     for (; i != finish; ++i) {
1879       if (traits_type::find(s, n, *i) != 0) {
1880         return i - begin();
1881       }
1882     }
1883     return npos;
1884   }
1885
1886   size_type find_first_of(const value_type* s, size_type pos = 0) const {
1887     return find_first_of(s, pos, traits_type::length(s));
1888   }
1889
1890   size_type find_first_of(value_type c, size_type pos = 0) const {
1891     return find_first_of(&c, pos, 1);
1892   }
1893
1894   size_type find_last_of (const basic_fbstring& str,
1895                           size_type pos = npos) const {
1896     return find_last_of(str.data(), pos, str.length());
1897   }
1898
1899   size_type find_last_of (const value_type* s, size_type pos,
1900                           size_type n) const {
1901     if (!empty() && n > 0) {
1902       pos = std::min(pos, length() - 1);
1903       const_iterator i(begin() + pos);
1904       for (;; --i) {
1905         if (traits_type::find(s, n, *i) != 0) {
1906           return i - begin();
1907         }
1908         if (i == begin()) break;
1909       }
1910     }
1911     return npos;
1912   }
1913
1914   size_type find_last_of (const value_type* s,
1915                           size_type pos = npos) const {
1916     return find_last_of(s, pos, traits_type::length(s));
1917   }
1918
1919   size_type find_last_of (value_type c, size_type pos = npos) const {
1920     return find_last_of(&c, pos, 1);
1921   }
1922
1923   size_type find_first_not_of(const basic_fbstring& str,
1924                               size_type pos = 0) const {
1925     return find_first_not_of(str.data(), pos, str.size());
1926   }
1927
1928   size_type find_first_not_of(const value_type* s, size_type pos,
1929                               size_type n) const {
1930     if (pos < length()) {
1931       const_iterator
1932         i(begin() + pos),
1933         finish(end());
1934       for (; i != finish; ++i) {
1935         if (traits_type::find(s, n, *i) == 0) {
1936           return i - begin();
1937         }
1938       }
1939     }
1940     return npos;
1941   }
1942
1943   size_type find_first_not_of(const value_type* s,
1944                               size_type pos = 0) const {
1945     return find_first_not_of(s, pos, traits_type::length(s));
1946   }
1947
1948   size_type find_first_not_of(value_type c, size_type pos = 0) const {
1949     return find_first_not_of(&c, pos, 1);
1950   }
1951
1952   size_type find_last_not_of(const basic_fbstring& str,
1953                              size_type pos = npos) const {
1954     return find_last_not_of(str.data(), pos, str.length());
1955   }
1956
1957   size_type find_last_not_of(const value_type* s, size_type pos,
1958                              size_type n) const {
1959     if (!this->empty()) {
1960       pos = std::min(pos, size() - 1);
1961       const_iterator i(begin() + pos);
1962       for (;; --i) {
1963         if (traits_type::find(s, n, *i) == 0) {
1964           return i - begin();
1965         }
1966         if (i == begin()) break;
1967       }
1968     }
1969     return npos;
1970   }
1971
1972   size_type find_last_not_of(const value_type* s,
1973                              size_type pos = npos) const {
1974     return find_last_not_of(s, pos, traits_type::length(s));
1975   }
1976
1977   size_type find_last_not_of (value_type c, size_type pos = npos) const {
1978     return find_last_not_of(&c, pos, 1);
1979   }
1980
1981   basic_fbstring substr(size_type pos = 0, size_type n = npos) const& {
1982     enforce(pos <= size(), std::__throw_out_of_range, "");
1983     return basic_fbstring(data() + pos, std::min(n, size() - pos));
1984   }
1985
1986   basic_fbstring substr(size_type pos = 0, size_type n = npos) && {
1987     enforce(pos <= size(), std::__throw_out_of_range, "");
1988     erase(0, pos);
1989     if (n < size()) resize(n);
1990     return std::move(*this);
1991   }
1992
1993   int compare(const basic_fbstring& str) const {
1994     // FIX due to Goncalo N M de Carvalho July 18, 2005
1995     return compare(0, size(), str);
1996   }
1997
1998   int compare(size_type pos1, size_type n1,
1999               const basic_fbstring& str) const {
2000     return compare(pos1, n1, str.data(), str.size());
2001   }
2002
2003   int compare(size_type pos1, size_type n1,
2004               const value_type* s) const {
2005     return compare(pos1, n1, s, traits_type::length(s));
2006   }
2007
2008   int compare(size_type pos1, size_type n1,
2009               const value_type* s, size_type n2) const {
2010     enforce(pos1 <= size(), std::__throw_out_of_range, "");
2011     procrustes(n1, size() - pos1);
2012     // The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
2013     const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
2014     return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2015   }
2016
2017   int compare(size_type pos1, size_type n1,
2018               const basic_fbstring& str,
2019               size_type pos2, size_type n2) const {
2020     enforce(pos2 <= str.size(), std::__throw_out_of_range, "");
2021     return compare(pos1, n1, str.data() + pos2,
2022                    std::min(n2, str.size() - pos2));
2023   }
2024
2025   // Code from Jean-Francois Bastien (03/26/2007)
2026   int compare(const value_type* s) const {
2027     // Could forward to compare(0, size(), s, traits_type::length(s))
2028     // but that does two extra checks
2029     const size_type n1(size()), n2(traits_type::length(s));
2030     const int r = traits_type::compare(data(), s, std::min(n1, n2));
2031     return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2032   }
2033
2034 private:
2035   // Data
2036   Storage store_;
2037 };
2038
2039 // non-member functions
2040 // C++11 21.4.8.1/1
2041 template <typename E, class T, class A, class S>
2042 inline
2043 basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
2044                                      const basic_fbstring<E, T, A, S>& rhs) {
2045
2046   basic_fbstring<E, T, A, S> result;
2047   result.reserve(lhs.size() + rhs.size());
2048   result.append(lhs).append(rhs);
2049   return std::move(result);
2050 }
2051
2052 // C++11 21.4.8.1/2
2053 template <typename E, class T, class A, class S>
2054 inline
2055 basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
2056                                      const basic_fbstring<E, T, A, S>& rhs) {
2057   return std::move(lhs.append(rhs));
2058 }
2059
2060 // C++11 21.4.8.1/3
2061 template <typename E, class T, class A, class S>
2062 inline
2063 basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
2064                                      basic_fbstring<E, T, A, S>&& rhs) {
2065   if (rhs.capacity() >= lhs.size() + rhs.size()) {
2066     // Good, at least we don't need to reallocate
2067     return std::move(rhs.insert(0, lhs));
2068   }
2069   // Meh, no go. Forward to operator+(const&, const&).
2070   auto const& rhsC = rhs;
2071   return lhs + rhsC;
2072 }
2073
2074 // C++11 21.4.8.1/4
2075 template <typename E, class T, class A, class S>
2076 inline
2077 basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
2078                                      basic_fbstring<E, T, A, S>&& rhs) {
2079   return std::move(lhs.append(rhs));
2080 }
2081
2082 // C++11 21.4.8.1/5
2083 template <typename E, class T, class A, class S>
2084 inline
2085 basic_fbstring<E, T, A, S> operator+(
2086   const E* lhs,
2087   const basic_fbstring<E, T, A, S>& rhs) {
2088   //
2089   basic_fbstring<E, T, A, S> result;
2090   const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
2091   result.reserve(len + rhs.size());
2092   result.append(lhs, len).append(rhs);
2093   return result;
2094 }
2095
2096 // C++11 21.4.8.1/6
2097 template <typename E, class T, class A, class S>
2098 inline
2099 basic_fbstring<E, T, A, S> operator+(
2100   const E* lhs,
2101   basic_fbstring<E, T, A, S>&& rhs) {
2102   //
2103   const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
2104   if (rhs.capacity() >= len + rhs.size()) {
2105     // Good, at least we don't need to reallocate
2106     return std::move(rhs.insert(rhs.begin(), lhs, lhs + len));
2107   }
2108   // Meh, no go. Do it by hand since we have len already.
2109   basic_fbstring<E, T, A, S> result;
2110   result.reserve(len + rhs.size());
2111   result.append(lhs, len).append(rhs);
2112   return result;
2113 }
2114
2115 // C++11 21.4.8.1/7
2116 template <typename E, class T, class A, class S>
2117 inline
2118 basic_fbstring<E, T, A, S> operator+(
2119   E lhs,
2120   const basic_fbstring<E, T, A, S>& rhs) {
2121
2122   basic_fbstring<E, T, A, S> result;
2123   result.reserve(1 + rhs.size());
2124   result.push_back(lhs);
2125   result.append(rhs);
2126   return result;
2127 }
2128
2129 // C++11 21.4.8.1/8
2130 template <typename E, class T, class A, class S>
2131 inline
2132 basic_fbstring<E, T, A, S> operator+(
2133   E lhs,
2134   basic_fbstring<E, T, A, S>&& rhs) {
2135   //
2136   if (rhs.capacity() > rhs.size()) {
2137     // Good, at least we don't need to reallocate
2138     return std::move(rhs.insert(rhs.begin(), lhs));
2139   }
2140   // Meh, no go. Forward to operator+(E, const&).
2141   auto const& rhsC = rhs;
2142   return lhs + rhsC;
2143 }
2144
2145 // C++11 21.4.8.1/9
2146 template <typename E, class T, class A, class S>
2147 inline
2148 basic_fbstring<E, T, A, S> operator+(
2149   const basic_fbstring<E, T, A, S>& lhs,
2150   const E* rhs) {
2151
2152   typedef typename basic_fbstring<E, T, A, S>::size_type size_type;
2153   typedef typename basic_fbstring<E, T, A, S>::traits_type traits_type;
2154
2155   basic_fbstring<E, T, A, S> result;
2156   const size_type len = traits_type::length(rhs);
2157   result.reserve(lhs.size() + len);
2158   result.append(lhs).append(rhs, len);
2159   return result;
2160 }
2161
2162 // C++11 21.4.8.1/10
2163 template <typename E, class T, class A, class S>
2164 inline
2165 basic_fbstring<E, T, A, S> operator+(
2166   basic_fbstring<E, T, A, S>&& lhs,
2167   const E* rhs) {
2168   //
2169   return std::move(lhs += rhs);
2170 }
2171
2172 // C++11 21.4.8.1/11
2173 template <typename E, class T, class A, class S>
2174 inline
2175 basic_fbstring<E, T, A, S> operator+(
2176   const basic_fbstring<E, T, A, S>& lhs,
2177   E rhs) {
2178
2179   basic_fbstring<E, T, A, S> result;
2180   result.reserve(lhs.size() + 1);
2181   result.append(lhs);
2182   result.push_back(rhs);
2183   return result;
2184 }
2185
2186 // C++11 21.4.8.1/12
2187 template <typename E, class T, class A, class S>
2188 inline
2189 basic_fbstring<E, T, A, S> operator+(
2190   basic_fbstring<E, T, A, S>&& lhs,
2191   E rhs) {
2192   //
2193   return std::move(lhs += rhs);
2194 }
2195
2196 template <typename E, class T, class A, class S>
2197 inline
2198 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2199                 const basic_fbstring<E, T, A, S>& rhs) {
2200   return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; }
2201
2202 template <typename E, class T, class A, class S>
2203 inline
2204 bool operator==(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2205                 const basic_fbstring<E, T, A, S>& rhs) {
2206   return rhs == lhs; }
2207
2208 template <typename E, class T, class A, class S>
2209 inline
2210 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2211                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2212   return lhs.compare(rhs) == 0; }
2213
2214 template <typename E, class T, class A, class S>
2215 inline
2216 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2217                 const basic_fbstring<E, T, A, S>& rhs) {
2218   return !(lhs == rhs); }
2219
2220 template <typename E, class T, class A, class S>
2221 inline
2222 bool operator!=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2223                 const basic_fbstring<E, T, A, S>& rhs) {
2224   return !(lhs == rhs); }
2225
2226 template <typename E, class T, class A, class S>
2227 inline
2228 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2229                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2230   return !(lhs == rhs); }
2231
2232 template <typename E, class T, class A, class S>
2233 inline
2234 bool operator<(const basic_fbstring<E, T, A, S>& lhs,
2235                const basic_fbstring<E, T, A, S>& rhs) {
2236   return lhs.compare(rhs) < 0; }
2237
2238 template <typename E, class T, class A, class S>
2239 inline
2240 bool operator<(const basic_fbstring<E, T, A, S>& lhs,
2241                const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2242   return lhs.compare(rhs) < 0; }
2243
2244 template <typename E, class T, class A, class S>
2245 inline
2246 bool operator<(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2247                const basic_fbstring<E, T, A, S>& rhs) {
2248   return rhs.compare(lhs) > 0; }
2249
2250 template <typename E, class T, class A, class S>
2251 inline
2252 bool operator>(const basic_fbstring<E, T, A, S>& lhs,
2253                const basic_fbstring<E, T, A, S>& rhs) {
2254   return rhs < lhs; }
2255
2256 template <typename E, class T, class A, class S>
2257 inline
2258 bool operator>(const basic_fbstring<E, T, A, S>& lhs,
2259                const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2260   return rhs < lhs; }
2261
2262 template <typename E, class T, class A, class S>
2263 inline
2264 bool operator>(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2265                const basic_fbstring<E, T, A, S>& rhs) {
2266   return rhs < lhs; }
2267
2268 template <typename E, class T, class A, class S>
2269 inline
2270 bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
2271                 const basic_fbstring<E, T, A, S>& rhs) {
2272   return !(rhs < lhs); }
2273
2274 template <typename E, class T, class A, class S>
2275 inline
2276 bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
2277                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2278   return !(rhs < lhs); }
2279
2280 template <typename E, class T, class A, class S>
2281 inline
2282 bool operator<=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2283                 const basic_fbstring<E, T, A, S>& rhs) {
2284   return !(rhs < lhs); }
2285
2286 template <typename E, class T, class A, class S>
2287 inline
2288 bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
2289                 const basic_fbstring<E, T, A, S>& rhs) {
2290   return !(lhs < rhs); }
2291
2292 template <typename E, class T, class A, class S>
2293 inline
2294 bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
2295                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2296   return !(lhs < rhs); }
2297
2298 template <typename E, class T, class A, class S>
2299 inline
2300 bool operator>=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2301                 const basic_fbstring<E, T, A, S>& rhs) {
2302  return !(lhs < rhs);
2303 }
2304
2305 // C++11 21.4.8.8
2306 template <typename E, class T, class A, class S>
2307 void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) {
2308   lhs.swap(rhs);
2309 }
2310
2311 // TODO: make this faster.
2312 template <typename E, class T, class A, class S>
2313 inline
2314 std::basic_istream<
2315   typename basic_fbstring<E, T, A, S>::value_type,
2316   typename basic_fbstring<E, T, A, S>::traits_type>&
2317   operator>>(
2318     std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2319     typename basic_fbstring<E, T, A, S>::traits_type>& is,
2320     basic_fbstring<E, T, A, S>& str) {
2321   typename std::basic_istream<E, T>::sentry sentry(is);
2322   typedef std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2323                              typename basic_fbstring<E, T, A, S>::traits_type>
2324                         __istream_type;
2325   typedef typename __istream_type::ios_base __ios_base;
2326   size_t extracted = 0;
2327   auto err = __ios_base::goodbit;
2328   if (sentry) {
2329     auto n = is.width();
2330     if (n <= 0) {
2331       n = str.max_size();
2332     }
2333     str.erase();
2334     for (auto got = is.rdbuf()->sgetc(); extracted != size_t(n); ++extracted) {
2335       if (got == T::eof()) {
2336         err |= __ios_base::eofbit;
2337         is.width(0);
2338         break;
2339       }
2340       if (isspace(got)) break;
2341       str.push_back(got);
2342       got = is.rdbuf()->snextc();
2343     }
2344   }
2345   if (!extracted) {
2346     err |= __ios_base::failbit;
2347   }
2348   if (err) {
2349     is.setstate(err);
2350   }
2351   return is;
2352 }
2353
2354 template <typename E, class T, class A, class S>
2355 inline
2356 std::basic_ostream<typename basic_fbstring<E, T, A, S>::value_type,
2357                    typename basic_fbstring<E, T, A, S>::traits_type>&
2358 operator<<(
2359   std::basic_ostream<typename basic_fbstring<E, T, A, S>::value_type,
2360   typename basic_fbstring<E, T, A, S>::traits_type>& os,
2361     const basic_fbstring<E, T, A, S>& str) {
2362 #if _LIBCPP_VERSION
2363   typename std::basic_ostream<
2364     typename basic_fbstring<E, T, A, S>::value_type,
2365     typename basic_fbstring<E, T, A, S>::traits_type>::sentry __s(os);
2366   if (__s) {
2367     typedef std::ostreambuf_iterator<
2368       typename basic_fbstring<E, T, A, S>::value_type,
2369       typename basic_fbstring<E, T, A, S>::traits_type> _Ip;
2370     size_t __len = str.size();
2371     bool __left =
2372       (os.flags() & std::ios_base::adjustfield) == std::ios_base::left;
2373     if (__pad_and_output(_Ip(os),
2374                          str.data(),
2375                          __left ? str.data() + __len : str.data(),
2376                          str.data() + __len,
2377                          os,
2378                          os.fill()).failed()) {
2379       os.setstate(std::ios_base::badbit | std::ios_base::failbit);
2380     }
2381   }
2382 #elif defined(_MSC_VER)
2383   // MSVC doesn't define __ostream_insert
2384   os.write(str.data(), str.size());
2385 #else
2386   std::__ostream_insert(os, str.data(), str.size());
2387 #endif
2388   return os;
2389 }
2390
2391 #ifndef _LIBSTDCXX_FBSTRING
2392
2393 template <typename E, class T, class A, class S>
2394 inline
2395 std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2396                    typename basic_fbstring<E, T, A, S>::traits_type>&
2397 getline(
2398   std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2399   typename basic_fbstring<E, T, A, S>::traits_type>& is,
2400     basic_fbstring<E, T, A, S>& str,
2401   typename basic_fbstring<E, T, A, S>::value_type delim) {
2402   // Use the nonstandard getdelim()
2403   char * buf = nullptr;
2404   size_t size = 0;
2405   for (;;) {
2406     // This looks quadratic but it really depends on realloc
2407     auto const newSize = size + 128;
2408     buf = static_cast<char*>(checkedRealloc(buf, newSize));
2409     is.getline(buf + size, newSize - size, delim);
2410     if (is.bad() || is.eof() || !is.fail()) {
2411       // done by either failure, end of file, or normal read
2412       size += std::strlen(buf + size);
2413       break;
2414     }
2415     // Here we have failed due to too short a buffer
2416     // Minus one to discount the terminating '\0'
2417     size = newSize - 1;
2418     assert(buf[size] == 0);
2419     // Clear the error so we can continue reading
2420     is.clear();
2421   }
2422   basic_fbstring<E, T, A, S> result(buf, size, size + 1,
2423                                     AcquireMallocatedString());
2424   result.swap(str);
2425   return is;
2426 }
2427
2428 template <typename E, class T, class A, class S>
2429 inline
2430 std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2431                    typename basic_fbstring<E, T, A, S>::traits_type>&
2432 getline(
2433   std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2434   typename basic_fbstring<E, T, A, S>::traits_type>& is,
2435   basic_fbstring<E, T, A, S>& str) {
2436   // Just forward to the version with a delimiter
2437   return getline(is, str, '\n');
2438 }
2439
2440 #endif
2441
2442 template <typename E1, class T, class A, class S>
2443 const typename basic_fbstring<E1, T, A, S>::size_type
2444 basic_fbstring<E1, T, A, S>::npos =
2445               static_cast<typename basic_fbstring<E1, T, A, S>::size_type>(-1);
2446
2447 #ifndef _LIBSTDCXX_FBSTRING
2448 // basic_string compatibility routines
2449
2450 template <typename E, class T, class A, class S>
2451 inline
2452 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2453                 const std::string& rhs) {
2454   return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) == 0;
2455 }
2456
2457 template <typename E, class T, class A, class S>
2458 inline
2459 bool operator==(const std::string& lhs,
2460                 const basic_fbstring<E, T, A, S>& rhs) {
2461   return rhs == lhs;
2462 }
2463
2464 template <typename E, class T, class A, class S>
2465 inline
2466 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2467                 const std::string& rhs) {
2468   return !(lhs == rhs);
2469 }
2470
2471 template <typename E, class T, class A, class S>
2472 inline
2473 bool operator!=(const std::string& lhs,
2474                 const basic_fbstring<E, T, A, S>& rhs) {
2475   return !(lhs == rhs);
2476 }
2477
2478 #if !defined(_LIBSTDCXX_FBSTRING)
2479 typedef basic_fbstring<char> fbstring;
2480 #endif
2481
2482 // fbstring is relocatable
2483 template <class T, class R, class A, class S>
2484 FOLLY_ASSUME_RELOCATABLE(basic_fbstring<T, R, A, S>);
2485
2486 #else
2487 _GLIBCXX_END_NAMESPACE_VERSION
2488 #endif
2489
2490 } // namespace folly
2491
2492 #ifndef _LIBSTDCXX_FBSTRING
2493
2494 // Hash functions to make fbstring usable with e.g. hash_map
2495 //
2496 // Handle interaction with different C++ standard libraries, which
2497 // expect these types to be in different namespaces.
2498
2499 #define FOLLY_FBSTRING_HASH1(T) \
2500   template <> \
2501   struct hash< ::folly::basic_fbstring<T> > { \
2502     size_t operator()(const ::folly::fbstring& s) const { \
2503       return ::folly::hash::fnv32_buf(s.data(), s.size()); \
2504     } \
2505   };
2506
2507 // The C++11 standard says that these four are defined
2508 #define FOLLY_FBSTRING_HASH \
2509   FOLLY_FBSTRING_HASH1(char) \
2510   FOLLY_FBSTRING_HASH1(char16_t) \
2511   FOLLY_FBSTRING_HASH1(char32_t) \
2512   FOLLY_FBSTRING_HASH1(wchar_t)
2513
2514 namespace std {
2515
2516 FOLLY_FBSTRING_HASH
2517
2518 }  // namespace std
2519
2520 #if FOLLY_HAVE_DEPRECATED_ASSOC
2521 #if defined(_GLIBCXX_SYMVER) && !defined(__BIONIC__)
2522 namespace __gnu_cxx {
2523
2524 FOLLY_FBSTRING_HASH
2525
2526 }  // namespace __gnu_cxx
2527 #endif // _GLIBCXX_SYMVER && !__BIONIC__
2528 #endif // FOLLY_HAVE_DEPRECATED_ASSOC
2529
2530 #undef FOLLY_FBSTRING_HASH
2531 #undef FOLLY_FBSTRING_HASH1
2532
2533 #endif // _LIBSTDCXX_FBSTRING
2534
2535 #pragma GCC diagnostic pop
2536
2537 #undef FBSTRING_DISABLE_ADDRESS_SANITIZER
2538 #undef throw
2539 #undef FBSTRING_LIKELY
2540 #undef FBSTRING_UNLIKELY
2541
2542 #endif // FOLLY_BASE_FBSTRING_H_