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