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