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