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