(Folly/FBString) Use a lambda to throw an exception for NULL input
[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
1058           ? traits_type::length(s)
1059           : [] {
1060               std::__throw_logic_error(
1061                 "basic_fbstring: null pointer initializer not valid");
1062               return 0;
1063             }()) {
1064   }
1065
1066   basic_fbstring(const value_type* s, size_type n, const A& a = A())
1067       : store_(s, n) {
1068   }
1069
1070   basic_fbstring(size_type n, value_type c, const A& a = A()) {
1071     auto const data = store_.expand_noinit(n);
1072     fbstring_detail::pod_fill(data, data + n, c);
1073     store_.writeTerminator();
1074   }
1075
1076   template <class InIt>
1077   basic_fbstring(InIt begin, InIt end,
1078                  typename std::enable_if<
1079                  !std::is_same<typename std::remove_const<InIt>::type,
1080                  value_type*>::value, const A>::type & a = A()) {
1081     assign(begin, end);
1082   }
1083
1084   // Specialization for const char*, const char*
1085   basic_fbstring(const value_type* b, const value_type* e)
1086       : store_(b, e - b) {
1087   }
1088
1089   // Nonstandard constructor
1090   basic_fbstring(value_type *s, size_type n, size_type c,
1091                  AcquireMallocatedString a)
1092       : store_(s, n, c, a) {
1093   }
1094
1095   // Construction from initialization list
1096   basic_fbstring(std::initializer_list<value_type> il) {
1097     assign(il.begin(), il.end());
1098   }
1099
1100   ~basic_fbstring() noexcept {
1101   }
1102
1103   basic_fbstring& operator=(const basic_fbstring& lhs) {
1104     if (FBSTRING_UNLIKELY(&lhs == this)) {
1105       return *this;
1106     }
1107     auto const oldSize = size();
1108     auto const srcSize = lhs.size();
1109     if (capacity() >= srcSize && !store_.isShared()) {
1110       // great, just copy the contents
1111       if (oldSize < srcSize)
1112         store_.expand_noinit(srcSize - oldSize);
1113       else
1114         store_.shrink(oldSize - srcSize);
1115       assert(size() == srcSize);
1116       fbstring_detail::pod_copy(lhs.begin(), lhs.end(), begin());
1117       store_.writeTerminator();
1118     } else {
1119       // need to reallocate, so we may as well create a brand new string
1120       basic_fbstring(lhs).swap(*this);
1121     }
1122     return *this;
1123   }
1124
1125   // Move assignment
1126   basic_fbstring& operator=(basic_fbstring&& goner) noexcept {
1127     if (FBSTRING_UNLIKELY(&goner == this)) {
1128       // Compatibility with std::basic_string<>,
1129       // C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support.
1130       return *this;
1131     }
1132     // No need of this anymore
1133     this->~basic_fbstring();
1134     // Move the goner into this
1135     new(&store_) fbstring_core<E>(std::move(goner.store_));
1136     return *this;
1137   }
1138
1139 #ifndef _LIBSTDCXX_FBSTRING
1140   // Compatibility with std::string
1141   basic_fbstring & operator=(const std::string & rhs) {
1142     return assign(rhs.data(), rhs.size());
1143   }
1144
1145   // Compatibility with std::string
1146   std::string toStdString() const {
1147     return std::string(data(), size());
1148   }
1149 #else
1150   // A lot of code in fbcode still uses this method, so keep it here for now.
1151   const basic_fbstring& toStdString() const {
1152     return *this;
1153   }
1154 #endif
1155
1156   basic_fbstring& operator=(const value_type* s) {
1157     return assign(s);
1158   }
1159
1160   basic_fbstring& operator=(value_type c) {
1161     if (empty()) {
1162       store_.expand_noinit(1);
1163     } else if (store_.isShared()) {
1164       basic_fbstring(1, c).swap(*this);
1165       return *this;
1166     } else {
1167       store_.shrink(size() - 1);
1168     }
1169     *store_.mutable_data() = c;
1170     store_.writeTerminator();
1171     return *this;
1172   }
1173
1174   basic_fbstring& operator=(std::initializer_list<value_type> il) {
1175     return assign(il.begin(), il.end());
1176   }
1177
1178   // C++11 21.4.3 iterators:
1179   iterator begin() { return store_.mutable_data(); }
1180
1181   const_iterator begin() const { return store_.data(); }
1182
1183   const_iterator cbegin() const { return begin(); }
1184
1185   iterator end() {
1186     return store_.mutable_data() + store_.size();
1187   }
1188
1189   const_iterator end() const {
1190     return store_.data() + store_.size();
1191   }
1192
1193   const_iterator cend() const { return end(); }
1194
1195   reverse_iterator rbegin() {
1196     return reverse_iterator(end());
1197   }
1198
1199   const_reverse_iterator rbegin() const {
1200     return const_reverse_iterator(end());
1201   }
1202
1203   const_reverse_iterator crbegin() const { return rbegin(); }
1204
1205   reverse_iterator rend() {
1206     return reverse_iterator(begin());
1207   }
1208
1209   const_reverse_iterator rend() const {
1210     return const_reverse_iterator(begin());
1211   }
1212
1213   const_reverse_iterator crend() const { return rend(); }
1214
1215   // Added by C++11
1216   // C++11 21.4.5, element access:
1217   const value_type& front() const { return *begin(); }
1218   const value_type& back() const {
1219     assert(!empty());
1220     // Should be begin()[size() - 1], but that branches twice
1221     return *(end() - 1);
1222   }
1223   value_type& front() { return *begin(); }
1224   value_type& back() {
1225     assert(!empty());
1226     // Should be begin()[size() - 1], but that branches twice
1227     return *(end() - 1);
1228   }
1229   void pop_back() {
1230     assert(!empty());
1231     store_.shrink(1);
1232   }
1233
1234   // C++11 21.4.4 capacity:
1235   size_type size() const { return store_.size(); }
1236
1237   size_type length() const { return size(); }
1238
1239   size_type max_size() const {
1240     return std::numeric_limits<size_type>::max();
1241   }
1242
1243   void resize(const size_type n, const value_type c = value_type()) {
1244     auto size = this->size();
1245     if (n <= size) {
1246       store_.shrink(size - n);
1247     } else {
1248       // Do this in two steps to minimize slack memory copied (see
1249       // smartRealloc).
1250       auto const capacity = this->capacity();
1251       assert(capacity >= size);
1252       if (size < capacity) {
1253         auto delta = std::min(n, capacity) - size;
1254         store_.expand_noinit(delta);
1255         fbstring_detail::pod_fill(begin() + size, end(), c);
1256         size += delta;
1257         if (size == n) {
1258           store_.writeTerminator();
1259           return;
1260         }
1261         assert(size < n);
1262       }
1263       auto const delta = n - size;
1264       store_.expand_noinit(delta);
1265       fbstring_detail::pod_fill(end() - delta, end(), c);
1266       store_.writeTerminator();
1267     }
1268     assert(this->size() == n);
1269   }
1270
1271   size_type capacity() const { return store_.capacity(); }
1272
1273   void reserve(size_type res_arg = 0) {
1274     enforce(res_arg <= max_size(), std::__throw_length_error, "");
1275     store_.reserve(res_arg);
1276   }
1277
1278   void shrink_to_fit() {
1279     // Shrink only if slack memory is sufficiently large
1280     if (capacity() < size() * 3 / 2) {
1281       return;
1282     }
1283     basic_fbstring(cbegin(), cend()).swap(*this);
1284   }
1285
1286   void clear() { resize(0); }
1287
1288   bool empty() const { return size() == 0; }
1289
1290   // C++11 21.4.5 element access:
1291   const_reference operator[](size_type pos) const {
1292     return *(c_str() + pos);
1293   }
1294
1295   reference operator[](size_type pos) {
1296     if (pos == size()) {
1297       // Just call c_str() to make sure '\0' is present
1298       c_str();
1299     }
1300     return *(begin() + pos);
1301   }
1302
1303   const_reference at(size_type n) const {
1304     enforce(n <= size(), std::__throw_out_of_range, "");
1305     return (*this)[n];
1306   }
1307
1308   reference at(size_type n) {
1309     enforce(n < size(), std::__throw_out_of_range, "");
1310     return (*this)[n];
1311   }
1312
1313   // C++11 21.4.6 modifiers:
1314   basic_fbstring& operator+=(const basic_fbstring& str) {
1315     return append(str);
1316   }
1317
1318   basic_fbstring& operator+=(const value_type* s) {
1319     return append(s);
1320   }
1321
1322   basic_fbstring& operator+=(const value_type c) {
1323     push_back(c);
1324     return *this;
1325   }
1326
1327   basic_fbstring& operator+=(std::initializer_list<value_type> il) {
1328     append(il);
1329     return *this;
1330   }
1331
1332   basic_fbstring& append(const basic_fbstring& str) {
1333 #ifndef NDEBUG
1334     auto desiredSize = size() + str.size();
1335 #endif
1336     append(str.data(), str.size());
1337     assert(size() == desiredSize);
1338     return *this;
1339   }
1340
1341   basic_fbstring& append(const basic_fbstring& str, const size_type pos,
1342                          size_type n) {
1343     const size_type sz = str.size();
1344     enforce(pos <= sz, std::__throw_out_of_range, "");
1345     procrustes(n, sz - pos);
1346     return append(str.data() + pos, n);
1347   }
1348
1349   basic_fbstring& append(const value_type* s, size_type n) {
1350 #ifndef NDEBUG
1351     Invariant checker(*this);
1352     (void) checker;
1353 #endif
1354     if (FBSTRING_UNLIKELY(!n)) {
1355       // Unlikely but must be done
1356       return *this;
1357     }
1358     auto const oldSize = size();
1359     auto const oldData = data();
1360     // Check for aliasing (rare). We could use "<=" here but in theory
1361     // those do not work for pointers unless the pointers point to
1362     // elements in the same array. For that reason we use
1363     // std::less_equal, which is guaranteed to offer a total order
1364     // over pointers. See discussion at http://goo.gl/Cy2ya for more
1365     // info.
1366     std::less_equal<const value_type*> le;
1367     if (FBSTRING_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) {
1368       assert(le(s + n, oldData + oldSize));
1369       const size_type offset = s - oldData;
1370       store_.reserve(oldSize + n);
1371       // Restore the source
1372       s = data() + offset;
1373     }
1374     // Warning! Repeated appends with short strings may actually incur
1375     // practically quadratic performance. Avoid that by pushing back
1376     // the first character (which ensures exponential growth) and then
1377     // appending the rest normally. Worst case the append may incur a
1378     // second allocation but that will be rare.
1379     push_back(*s++);
1380     --n;
1381     memcpy(store_.expand_noinit(n), s, n * sizeof(value_type));
1382     assert(size() == oldSize + n + 1);
1383     return *this;
1384   }
1385
1386   basic_fbstring& append(const value_type* s) {
1387     return append(s, traits_type::length(s));
1388   }
1389
1390   basic_fbstring& append(size_type n, value_type c) {
1391     resize(size() + n, c);
1392     return *this;
1393   }
1394
1395   template<class InputIterator>
1396   basic_fbstring& append(InputIterator first, InputIterator last) {
1397     insert(end(), first, last);
1398     return *this;
1399   }
1400
1401   basic_fbstring& append(std::initializer_list<value_type> il) {
1402     return append(il.begin(), il.end());
1403   }
1404
1405   void push_back(const value_type c) {             // primitive
1406     store_.push_back(c);
1407   }
1408
1409   basic_fbstring& assign(const basic_fbstring& str) {
1410     if (&str == this) return *this;
1411     return assign(str.data(), str.size());
1412   }
1413
1414   basic_fbstring& assign(basic_fbstring&& str) {
1415     return *this = std::move(str);
1416   }
1417
1418   basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
1419                          size_type n) {
1420     const size_type sz = str.size();
1421     enforce(pos <= sz, std::__throw_out_of_range, "");
1422     procrustes(n, sz - pos);
1423     return assign(str.data() + pos, n);
1424   }
1425
1426   basic_fbstring& assign(const value_type* s, const size_type n) {
1427     Invariant checker(*this);
1428     (void) checker;
1429     if (size() >= n) {
1430       std::copy(s, s + n, begin());
1431       resize(n);
1432       assert(size() == n);
1433     } else {
1434       const value_type *const s2 = s + size();
1435       std::copy(s, s2, begin());
1436       append(s2, n - size());
1437       assert(size() == n);
1438     }
1439     store_.writeTerminator();
1440     assert(size() == n);
1441     return *this;
1442   }
1443
1444   basic_fbstring& assign(const value_type* s) {
1445     return assign(s, traits_type::length(s));
1446   }
1447
1448   basic_fbstring& assign(std::initializer_list<value_type> il) {
1449     return assign(il.begin(), il.end());
1450   }
1451
1452   template <class ItOrLength, class ItOrChar>
1453   basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) {
1454     return replace(begin(), end(), first_or_n, last_or_c);
1455   }
1456
1457   basic_fbstring& insert(size_type pos1, const basic_fbstring& str) {
1458     return insert(pos1, str.data(), str.size());
1459   }
1460
1461   basic_fbstring& insert(size_type pos1, const basic_fbstring& str,
1462                          size_type pos2, size_type n) {
1463     enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
1464     procrustes(n, str.length() - pos2);
1465     return insert(pos1, str.data() + pos2, n);
1466   }
1467
1468   basic_fbstring& insert(size_type pos, const value_type* s, size_type n) {
1469     enforce(pos <= length(), std::__throw_out_of_range, "");
1470     insert(begin() + pos, s, s + n);
1471     return *this;
1472   }
1473
1474   basic_fbstring& insert(size_type pos, const value_type* s) {
1475     return insert(pos, s, traits_type::length(s));
1476   }
1477
1478   basic_fbstring& insert(size_type pos, size_type n, value_type c) {
1479     enforce(pos <= length(), std::__throw_out_of_range, "");
1480     insert(begin() + pos, n, c);
1481     return *this;
1482   }
1483
1484   iterator insert(const_iterator p, const value_type c) {
1485     const size_type pos = p - begin();
1486     insert(p, 1, c);
1487     return begin() + pos;
1488   }
1489
1490 private:
1491   template <int i> class Selector {};
1492
1493   iterator insertImplDiscr(const_iterator p,
1494                            size_type n, value_type c, Selector<1>) {
1495     Invariant checker(*this);
1496     (void) checker;
1497     auto const pos = p - begin();
1498     assert(p >= begin() && p <= end());
1499     if (capacity() - size() < n) {
1500       const size_type sz = p - begin();
1501       reserve(size() + n);
1502       p = begin() + sz;
1503     }
1504     const iterator oldEnd = end();
1505     if (n < size_type(oldEnd - p)) {
1506       append(oldEnd - n, oldEnd);
1507       //std::copy(
1508       //    reverse_iterator(oldEnd - n),
1509       //    reverse_iterator(p),
1510       //    reverse_iterator(oldEnd));
1511       fbstring_detail::pod_move(&*p, &*oldEnd - n,
1512                                 begin() + pos + n);
1513       std::fill(begin() + pos, begin() + pos + n, c);
1514     } else {
1515       append(n - (end() - p), c);
1516       append(iterator(p), oldEnd);
1517       std::fill(iterator(p), oldEnd, c);
1518     }
1519     store_.writeTerminator();
1520     return begin() + pos;
1521   }
1522
1523   template<class InputIter>
1524   iterator insertImplDiscr(const_iterator i,
1525                            InputIter b, InputIter e, Selector<0>) {
1526     return insertImpl(i, b, e,
1527                typename std::iterator_traits<InputIter>::iterator_category());
1528   }
1529
1530   template <class FwdIterator>
1531   iterator insertImpl(const_iterator i,
1532                   FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
1533     Invariant checker(*this);
1534     (void) checker;
1535     const size_type pos = i - begin();
1536     const typename std::iterator_traits<FwdIterator>::difference_type n2 =
1537       std::distance(s1, s2);
1538     assert(n2 >= 0);
1539     using namespace fbstring_detail;
1540     assert(pos <= size());
1541
1542     const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
1543       capacity() - size();
1544     if (maxn2 < n2) {
1545       // realloc the string
1546       reserve(size() + n2);
1547       i = begin() + pos;
1548     }
1549     if (pos + n2 <= size()) {
1550       const iterator tailBegin = end() - n2;
1551       store_.expand_noinit(n2);
1552       fbstring_detail::pod_copy(tailBegin, tailBegin + n2, end() - n2);
1553       std::copy(const_reverse_iterator(tailBegin), const_reverse_iterator(i),
1554                 reverse_iterator(tailBegin + n2));
1555       std::copy(s1, s2, begin() + pos);
1556     } else {
1557       FwdIterator t = s1;
1558       const size_type old_size = size();
1559       std::advance(t, old_size - pos);
1560       const size_t newElems = std::distance(t, s2);
1561       store_.expand_noinit(n2);
1562       std::copy(t, s2, begin() + old_size);
1563       fbstring_detail::pod_copy(data() + pos, data() + old_size,
1564                                  begin() + old_size + newElems);
1565       std::copy(s1, t, begin() + pos);
1566     }
1567     store_.writeTerminator();
1568     return begin() + pos;
1569   }
1570
1571   template <class InputIterator>
1572   iterator insertImpl(const_iterator i,
1573                       InputIterator b, InputIterator e,
1574                       std::input_iterator_tag) {
1575     const auto pos = i - begin();
1576     basic_fbstring temp(begin(), i);
1577     for (; b != e; ++b) {
1578       temp.push_back(*b);
1579     }
1580     temp.append(i, cend());
1581     swap(temp);
1582     return begin() + pos;
1583   }
1584
1585 public:
1586   template <class ItOrLength, class ItOrChar>
1587   iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
1588     Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
1589     return insertImplDiscr(p, first_or_n, last_or_c, sel);
1590   }
1591
1592   iterator insert(const_iterator p, std::initializer_list<value_type> il) {
1593     return insert(p, il.begin(), il.end());
1594   }
1595
1596   basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
1597     Invariant checker(*this);
1598     (void) checker;
1599     enforce(pos <= length(), std::__throw_out_of_range, "");
1600     procrustes(n, length() - pos);
1601     std::copy(begin() + pos + n, end(), begin() + pos);
1602     resize(length() - n);
1603     return *this;
1604   }
1605
1606   iterator erase(iterator position) {
1607     const size_type pos(position - begin());
1608     enforce(pos <= size(), std::__throw_out_of_range, "");
1609     erase(pos, 1);
1610     return begin() + pos;
1611   }
1612
1613   iterator erase(iterator first, iterator last) {
1614     const size_type pos(first - begin());
1615     erase(pos, last - first);
1616     return begin() + pos;
1617   }
1618
1619   // Replaces at most n1 chars of *this, starting with pos1 with the
1620   // content of str
1621   basic_fbstring& replace(size_type pos1, size_type n1,
1622                           const basic_fbstring& str) {
1623     return replace(pos1, n1, str.data(), str.size());
1624   }
1625
1626   // Replaces at most n1 chars of *this, starting with pos1,
1627   // with at most n2 chars of str starting with pos2
1628   basic_fbstring& replace(size_type pos1, size_type n1,
1629                           const basic_fbstring& str,
1630                           size_type pos2, size_type n2) {
1631     enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
1632     return replace(pos1, n1, str.data() + pos2,
1633                    std::min(n2, str.size() - pos2));
1634   }
1635
1636   // Replaces at most n1 chars of *this, starting with pos, with chars from s
1637   basic_fbstring& replace(size_type pos, size_type n1, const value_type* s) {
1638     return replace(pos, n1, s, traits_type::length(s));
1639   }
1640
1641   // Replaces at most n1 chars of *this, starting with pos, with n2
1642   // occurrences of c
1643   //
1644   // consolidated with
1645   //
1646   // Replaces at most n1 chars of *this, starting with pos, with at
1647   // most n2 chars of str.  str must have at least n2 chars.
1648   template <class StrOrLength, class NumOrChar>
1649   basic_fbstring& replace(size_type pos, size_type n1,
1650                           StrOrLength s_or_n2, NumOrChar n_or_c) {
1651     Invariant checker(*this);
1652     (void) checker;
1653     enforce(pos <= size(), std::__throw_out_of_range, "");
1654     procrustes(n1, length() - pos);
1655     const iterator b = begin() + pos;
1656     return replace(b, b + n1, s_or_n2, n_or_c);
1657   }
1658
1659   basic_fbstring& replace(iterator i1, iterator i2, const basic_fbstring& str) {
1660     return replace(i1, i2, str.data(), str.length());
1661   }
1662
1663   basic_fbstring& replace(iterator i1, iterator i2, const value_type* s) {
1664     return replace(i1, i2, s, traits_type::length(s));
1665   }
1666
1667 private:
1668   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1669                                    const value_type* s, size_type n,
1670                                    Selector<2>) {
1671     assert(i1 <= i2);
1672     assert(begin() <= i1 && i1 <= end());
1673     assert(begin() <= i2 && i2 <= end());
1674     return replace(i1, i2, s, s + n);
1675   }
1676
1677   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1678                                    size_type n2, value_type c, Selector<1>) {
1679     const size_type n1 = i2 - i1;
1680     if (n1 > n2) {
1681       std::fill(i1, i1 + n2, c);
1682       erase(i1 + n2, i2);
1683     } else {
1684       std::fill(i1, i2, c);
1685       insert(i2, n2 - n1, c);
1686     }
1687     assert(isSane());
1688     return *this;
1689   }
1690
1691   template <class InputIter>
1692   basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
1693                                    InputIter b, InputIter e,
1694                                    Selector<0>) {
1695     replaceImpl(i1, i2, b, e,
1696                 typename std::iterator_traits<InputIter>::iterator_category());
1697     return *this;
1698   }
1699
1700 private:
1701   template <class FwdIterator>
1702   bool replaceAliased(iterator i1, iterator i2,
1703                       FwdIterator s1, FwdIterator s2, std::false_type) {
1704     return false;
1705   }
1706
1707   template <class FwdIterator>
1708   bool replaceAliased(iterator i1, iterator i2,
1709                       FwdIterator s1, FwdIterator s2, std::true_type) {
1710     static const std::less_equal<const value_type*> le =
1711       std::less_equal<const value_type*>();
1712     const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
1713     if (!aliased) {
1714       return false;
1715     }
1716     // Aliased replace, copy to new string
1717     basic_fbstring temp;
1718     temp.reserve(size() - (i2 - i1) + std::distance(s1, s2));
1719     temp.append(begin(), i1).append(s1, s2).append(i2, end());
1720     swap(temp);
1721     return true;
1722   }
1723
1724   template <class FwdIterator>
1725   void replaceImpl(iterator i1, iterator i2,
1726                    FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
1727     Invariant checker(*this);
1728     (void) checker;
1729
1730     // Handle aliased replace
1731     if (replaceAliased(i1, i2, s1, s2,
1732           std::integral_constant<bool,
1733             std::is_same<FwdIterator, iterator>::value ||
1734             std::is_same<FwdIterator, const_iterator>::value>())) {
1735       return;
1736     }
1737
1738     auto const n1 = i2 - i1;
1739     assert(n1 >= 0);
1740     auto const n2 = std::distance(s1, s2);
1741     assert(n2 >= 0);
1742
1743     if (n1 > n2) {
1744       // shrinks
1745       std::copy(s1, s2, i1);
1746       erase(i1 + n2, i2);
1747     } else {
1748       // grows
1749       fbstring_detail::copy_n(s1, n1, i1);
1750       std::advance(s1, n1);
1751       insert(i2, s1, s2);
1752     }
1753     assert(isSane());
1754   }
1755
1756   template <class InputIterator>
1757   void replaceImpl(iterator i1, iterator i2,
1758                    InputIterator b, InputIterator e, std::input_iterator_tag) {
1759     basic_fbstring temp(begin(), i1);
1760     temp.append(b, e).append(i2, end());
1761     swap(temp);
1762   }
1763
1764 public:
1765   template <class T1, class T2>
1766   basic_fbstring& replace(iterator i1, iterator i2,
1767                           T1 first_or_n_or_s, T2 last_or_c_or_n) {
1768     const bool
1769       num1 = std::numeric_limits<T1>::is_specialized,
1770       num2 = std::numeric_limits<T2>::is_specialized;
1771     return replaceImplDiscr(
1772       i1, i2, first_or_n_or_s, last_or_c_or_n,
1773       Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
1774   }
1775
1776   size_type copy(value_type* s, size_type n, size_type pos = 0) const {
1777     enforce(pos <= size(), std::__throw_out_of_range, "");
1778     procrustes(n, size() - pos);
1779
1780     fbstring_detail::pod_copy(
1781       data() + pos,
1782       data() + pos + n,
1783       s);
1784     return n;
1785   }
1786
1787   void swap(basic_fbstring& rhs) {
1788     store_.swap(rhs.store_);
1789   }
1790
1791   const value_type* c_str() const {
1792     return store_.c_str();
1793   }
1794
1795   const value_type* data() const { return c_str(); }
1796
1797   allocator_type get_allocator() const {
1798     return allocator_type();
1799   }
1800
1801   size_type find(const basic_fbstring& str, size_type pos = 0) const {
1802     return find(str.data(), pos, str.length());
1803   }
1804
1805   size_type find(const value_type* needle, const size_type pos,
1806                  const size_type nsize) const {
1807     if (!nsize) return pos;
1808     auto const size = this->size();
1809     // nsize + pos can overflow (eg pos == npos), guard against that by checking
1810     // that nsize + pos does not wrap around.
1811     if (nsize + pos > size || nsize + pos < pos) return npos;
1812     // Don't use std::search, use a Boyer-Moore-like trick by comparing
1813     // the last characters first
1814     auto const haystack = data();
1815     auto const nsize_1 = nsize - 1;
1816     auto const lastNeedle = needle[nsize_1];
1817
1818     // Boyer-Moore skip value for the last char in the needle. Zero is
1819     // not a valid value; skip will be computed the first time it's
1820     // needed.
1821     size_type skip = 0;
1822
1823     const E * i = haystack + pos;
1824     auto iEnd = haystack + size - nsize_1;
1825
1826     while (i < iEnd) {
1827       // Boyer-Moore: match the last element in the needle
1828       while (i[nsize_1] != lastNeedle) {
1829         if (++i == iEnd) {
1830           // not found
1831           return npos;
1832         }
1833       }
1834       // Here we know that the last char matches
1835       // Continue in pedestrian mode
1836       for (size_t j = 0; ; ) {
1837         assert(j < nsize);
1838         if (i[j] != needle[j]) {
1839           // Not found, we can skip
1840           // Compute the skip value lazily
1841           if (skip == 0) {
1842             skip = 1;
1843             while (skip <= nsize_1 && needle[nsize_1 - skip] != lastNeedle) {
1844               ++skip;
1845             }
1846           }
1847           i += skip;
1848           break;
1849         }
1850         // Check if done searching
1851         if (++j == nsize) {
1852           // Yay
1853           return i - haystack;
1854         }
1855       }
1856     }
1857     return npos;
1858   }
1859
1860   size_type find(const value_type* s, size_type pos = 0) const {
1861     return find(s, pos, traits_type::length(s));
1862   }
1863
1864   size_type find (value_type c, size_type pos = 0) const {
1865     return find(&c, pos, 1);
1866   }
1867
1868   size_type rfind(const basic_fbstring& str, size_type pos = npos) const {
1869     return rfind(str.data(), pos, str.length());
1870   }
1871
1872   size_type rfind(const value_type* s, size_type pos, size_type n) const {
1873     if (n > length()) return npos;
1874     pos = std::min(pos, length() - n);
1875     if (n == 0) return pos;
1876
1877     const_iterator i(begin() + pos);
1878     for (; ; --i) {
1879       if (traits_type::eq(*i, *s)
1880           && traits_type::compare(&*i, s, n) == 0) {
1881         return i - begin();
1882       }
1883       if (i == begin()) break;
1884     }
1885     return npos;
1886   }
1887
1888   size_type rfind(const value_type* s, size_type pos = npos) const {
1889     return rfind(s, pos, traits_type::length(s));
1890   }
1891
1892   size_type rfind(value_type c, size_type pos = npos) const {
1893     return rfind(&c, pos, 1);
1894   }
1895
1896   size_type find_first_of(const basic_fbstring& str, size_type pos = 0) const {
1897     return find_first_of(str.data(), pos, str.length());
1898   }
1899
1900   size_type find_first_of(const value_type* s,
1901                           size_type pos, size_type n) const {
1902     if (pos > length() || n == 0) return npos;
1903     const_iterator i(begin() + pos),
1904       finish(end());
1905     for (; i != finish; ++i) {
1906       if (traits_type::find(s, n, *i) != 0) {
1907         return i - begin();
1908       }
1909     }
1910     return npos;
1911   }
1912
1913   size_type find_first_of(const value_type* s, size_type pos = 0) const {
1914     return find_first_of(s, pos, traits_type::length(s));
1915   }
1916
1917   size_type find_first_of(value_type c, size_type pos = 0) const {
1918     return find_first_of(&c, pos, 1);
1919   }
1920
1921   size_type find_last_of (const basic_fbstring& str,
1922                           size_type pos = npos) const {
1923     return find_last_of(str.data(), pos, str.length());
1924   }
1925
1926   size_type find_last_of (const value_type* s, size_type pos,
1927                           size_type n) const {
1928     if (!empty() && n > 0) {
1929       pos = std::min(pos, length() - 1);
1930       const_iterator i(begin() + pos);
1931       for (;; --i) {
1932         if (traits_type::find(s, n, *i) != 0) {
1933           return i - begin();
1934         }
1935         if (i == begin()) break;
1936       }
1937     }
1938     return npos;
1939   }
1940
1941   size_type find_last_of (const value_type* s,
1942                           size_type pos = npos) const {
1943     return find_last_of(s, pos, traits_type::length(s));
1944   }
1945
1946   size_type find_last_of (value_type c, size_type pos = npos) const {
1947     return find_last_of(&c, pos, 1);
1948   }
1949
1950   size_type find_first_not_of(const basic_fbstring& str,
1951                               size_type pos = 0) const {
1952     return find_first_not_of(str.data(), pos, str.size());
1953   }
1954
1955   size_type find_first_not_of(const value_type* s, size_type pos,
1956                               size_type n) const {
1957     if (pos < length()) {
1958       const_iterator
1959         i(begin() + pos),
1960         finish(end());
1961       for (; i != finish; ++i) {
1962         if (traits_type::find(s, n, *i) == 0) {
1963           return i - begin();
1964         }
1965       }
1966     }
1967     return npos;
1968   }
1969
1970   size_type find_first_not_of(const value_type* s,
1971                               size_type pos = 0) const {
1972     return find_first_not_of(s, pos, traits_type::length(s));
1973   }
1974
1975   size_type find_first_not_of(value_type c, size_type pos = 0) const {
1976     return find_first_not_of(&c, pos, 1);
1977   }
1978
1979   size_type find_last_not_of(const basic_fbstring& str,
1980                              size_type pos = npos) const {
1981     return find_last_not_of(str.data(), pos, str.length());
1982   }
1983
1984   size_type find_last_not_of(const value_type* s, size_type pos,
1985                              size_type n) const {
1986     if (!this->empty()) {
1987       pos = std::min(pos, size() - 1);
1988       const_iterator i(begin() + pos);
1989       for (;; --i) {
1990         if (traits_type::find(s, n, *i) == 0) {
1991           return i - begin();
1992         }
1993         if (i == begin()) break;
1994       }
1995     }
1996     return npos;
1997   }
1998
1999   size_type find_last_not_of(const value_type* s,
2000                              size_type pos = npos) const {
2001     return find_last_not_of(s, pos, traits_type::length(s));
2002   }
2003
2004   size_type find_last_not_of (value_type c, size_type pos = npos) const {
2005     return find_last_not_of(&c, pos, 1);
2006   }
2007
2008   basic_fbstring substr(size_type pos = 0, size_type n = npos) const {
2009     enforce(pos <= size(), std::__throw_out_of_range, "");
2010     return basic_fbstring(data() + pos, std::min(n, size() - pos));
2011   }
2012
2013   int compare(const basic_fbstring& str) const {
2014     // FIX due to Goncalo N M de Carvalho July 18, 2005
2015     return compare(0, size(), str);
2016   }
2017
2018   int compare(size_type pos1, size_type n1,
2019               const basic_fbstring& str) const {
2020     return compare(pos1, n1, str.data(), str.size());
2021   }
2022
2023   int compare(size_type pos1, size_type n1,
2024               const value_type* s) const {
2025     return compare(pos1, n1, s, traits_type::length(s));
2026   }
2027
2028   int compare(size_type pos1, size_type n1,
2029               const value_type* s, size_type n2) const {
2030     enforce(pos1 <= size(), std::__throw_out_of_range, "");
2031     procrustes(n1, size() - pos1);
2032     // The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
2033     const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
2034     return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2035   }
2036
2037   int compare(size_type pos1, size_type n1,
2038               const basic_fbstring& str,
2039               size_type pos2, size_type n2) const {
2040     enforce(pos2 <= str.size(), std::__throw_out_of_range, "");
2041     return compare(pos1, n1, str.data() + pos2,
2042                    std::min(n2, str.size() - pos2));
2043   }
2044
2045   // Code from Jean-Francois Bastien (03/26/2007)
2046   int compare(const value_type* s) const {
2047     // Could forward to compare(0, size(), s, traits_type::length(s))
2048     // but that does two extra checks
2049     const size_type n1(size()), n2(traits_type::length(s));
2050     const int r = traits_type::compare(data(), s, std::min(n1, n2));
2051     return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
2052   }
2053
2054 private:
2055   // Data
2056   Storage store_;
2057 };
2058
2059 // non-member functions
2060 // C++11 21.4.8.1/2
2061 template <typename E, class T, class A, class S>
2062 inline
2063 basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
2064                                      const basic_fbstring<E, T, A, S>& rhs) {
2065
2066   basic_fbstring<E, T, A, S> result;
2067   result.reserve(lhs.size() + rhs.size());
2068   result.append(lhs).append(rhs);
2069   return std::move(result);
2070 }
2071
2072 // C++11 21.4.8.1/2
2073 template <typename E, class T, class A, class S>
2074 inline
2075 basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
2076                                      const basic_fbstring<E, T, A, S>& rhs) {
2077   return std::move(lhs.append(rhs));
2078 }
2079
2080 // C++11 21.4.8.1/3
2081 template <typename E, class T, class A, class S>
2082 inline
2083 basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
2084                                      basic_fbstring<E, T, A, S>&& rhs) {
2085   if (rhs.capacity() >= lhs.size() + rhs.size()) {
2086     // Good, at least we don't need to reallocate
2087     return std::move(rhs.insert(0, lhs));
2088   }
2089   // Meh, no go. Forward to operator+(const&, const&).
2090   auto const& rhsC = rhs;
2091   return lhs + rhsC;
2092 }
2093
2094 // C++11 21.4.8.1/4
2095 template <typename E, class T, class A, class S>
2096 inline
2097 basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
2098                                      basic_fbstring<E, T, A, S>&& rhs) {
2099   return std::move(lhs.append(rhs));
2100 }
2101
2102 template <typename E, class T, class A, class S>
2103 inline
2104 basic_fbstring<E, T, A, S> operator+(
2105   const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2106   const basic_fbstring<E, T, A, S>& rhs) {
2107   //
2108   basic_fbstring<E, T, A, S> result;
2109   const typename basic_fbstring<E, T, A, S>::size_type len =
2110     basic_fbstring<E, T, A, S>::traits_type::length(lhs);
2111   result.reserve(len + rhs.size());
2112   result.append(lhs, len).append(rhs);
2113   return result;
2114 }
2115
2116 template <typename E, class T, class A, class S>
2117 inline
2118 basic_fbstring<E, T, A, S> operator+(
2119   typename basic_fbstring<E, T, A, S>::value_type lhs,
2120   const basic_fbstring<E, T, A, S>& rhs) {
2121
2122   basic_fbstring<E, T, A, S> result;
2123   result.reserve(1 + rhs.size());
2124   result.push_back(lhs);
2125   result.append(rhs);
2126   return result;
2127 }
2128
2129 template <typename E, class T, class A, class S>
2130 inline
2131 basic_fbstring<E, T, A, S> operator+(
2132   const basic_fbstring<E, T, A, S>& lhs,
2133   const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2134
2135   typedef typename basic_fbstring<E, T, A, S>::size_type size_type;
2136   typedef typename basic_fbstring<E, T, A, S>::traits_type traits_type;
2137
2138   basic_fbstring<E, T, A, S> result;
2139   const size_type len = traits_type::length(rhs);
2140   result.reserve(lhs.size() + len);
2141   result.append(lhs).append(rhs, len);
2142   return result;
2143 }
2144
2145 template <typename E, class T, class A, class S>
2146 inline
2147 basic_fbstring<E, T, A, S> operator+(
2148   const basic_fbstring<E, T, A, S>& lhs,
2149   typename basic_fbstring<E, T, A, S>::value_type rhs) {
2150
2151   basic_fbstring<E, T, A, S> result;
2152   result.reserve(lhs.size() + 1);
2153   result.append(lhs);
2154   result.push_back(rhs);
2155   return result;
2156 }
2157
2158 template <typename E, class T, class A, class S>
2159 inline
2160 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2161                 const basic_fbstring<E, T, A, S>& rhs) {
2162   return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; }
2163
2164 template <typename E, class T, class A, class S>
2165 inline
2166 bool operator==(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2167                 const basic_fbstring<E, T, A, S>& rhs) {
2168   return rhs == lhs; }
2169
2170 template <typename E, class T, class A, class S>
2171 inline
2172 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2173                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2174   return lhs.compare(rhs) == 0; }
2175
2176 template <typename E, class T, class A, class S>
2177 inline
2178 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2179                 const basic_fbstring<E, T, A, S>& rhs) {
2180   return !(lhs == rhs); }
2181
2182 template <typename E, class T, class A, class S>
2183 inline
2184 bool operator!=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2185                 const basic_fbstring<E, T, A, S>& rhs) {
2186   return !(lhs == rhs); }
2187
2188 template <typename E, class T, class A, class S>
2189 inline
2190 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2191                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2192   return !(lhs == rhs); }
2193
2194 template <typename E, class T, class A, class S>
2195 inline
2196 bool operator<(const basic_fbstring<E, T, A, S>& lhs,
2197                const basic_fbstring<E, T, A, S>& rhs) {
2198   return lhs.compare(rhs) < 0; }
2199
2200 template <typename E, class T, class A, class S>
2201 inline
2202 bool operator<(const basic_fbstring<E, T, A, S>& lhs,
2203                const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2204   return lhs.compare(rhs) < 0; }
2205
2206 template <typename E, class T, class A, class S>
2207 inline
2208 bool operator<(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2209                const basic_fbstring<E, T, A, S>& rhs) {
2210   return rhs.compare(lhs) > 0; }
2211
2212 template <typename E, class T, class A, class S>
2213 inline
2214 bool operator>(const basic_fbstring<E, T, A, S>& lhs,
2215                const basic_fbstring<E, T, A, S>& rhs) {
2216   return rhs < lhs; }
2217
2218 template <typename E, class T, class A, class S>
2219 inline
2220 bool operator>(const basic_fbstring<E, T, A, S>& lhs,
2221                const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2222   return rhs < lhs; }
2223
2224 template <typename E, class T, class A, class S>
2225 inline
2226 bool operator>(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2227                const basic_fbstring<E, T, A, S>& rhs) {
2228   return rhs < lhs; }
2229
2230 template <typename E, class T, class A, class S>
2231 inline
2232 bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
2233                 const basic_fbstring<E, T, A, S>& rhs) {
2234   return !(rhs < lhs); }
2235
2236 template <typename E, class T, class A, class S>
2237 inline
2238 bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
2239                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2240   return !(rhs < lhs); }
2241
2242 template <typename E, class T, class A, class S>
2243 inline
2244 bool operator<=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2245                 const basic_fbstring<E, T, A, S>& rhs) {
2246   return !(rhs < lhs); }
2247
2248 template <typename E, class T, class A, class S>
2249 inline
2250 bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
2251                 const basic_fbstring<E, T, A, S>& rhs) {
2252   return !(lhs < rhs); }
2253
2254 template <typename E, class T, class A, class S>
2255 inline
2256 bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
2257                 const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
2258   return !(lhs < rhs); }
2259
2260 template <typename E, class T, class A, class S>
2261 inline
2262 bool operator>=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
2263                 const basic_fbstring<E, T, A, S>& rhs) {
2264  return !(lhs < rhs);
2265 }
2266
2267 // C++11 21.4.8.8
2268 template <typename E, class T, class A, class S>
2269 void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) {
2270   lhs.swap(rhs);
2271 }
2272
2273 // TODO: make this faster.
2274 template <typename E, class T, class A, class S>
2275 inline
2276 std::basic_istream<
2277   typename basic_fbstring<E, T, A, S>::value_type,
2278   typename basic_fbstring<E, T, A, S>::traits_type>&
2279   operator>>(
2280     std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2281     typename basic_fbstring<E, T, A, S>::traits_type>& is,
2282     basic_fbstring<E, T, A, S>& str) {
2283   typename std::basic_istream<E, T>::sentry sentry(is);
2284   typedef std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2285                              typename basic_fbstring<E, T, A, S>::traits_type>
2286                         __istream_type;
2287   typedef typename __istream_type::ios_base __ios_base;
2288   size_t extracted = 0;
2289   auto err = __ios_base::goodbit;
2290   if (sentry) {
2291     auto n = is.width();
2292     if (n == 0) {
2293       n = str.max_size();
2294     }
2295     str.erase();
2296     auto got = is.rdbuf()->sgetc();
2297     for (; extracted != n && got != T::eof() && !isspace(got); ++extracted) {
2298       // Whew. We get to store this guy
2299       str.push_back(got);
2300       got = is.rdbuf()->snextc();
2301     }
2302     if (got == T::eof()) {
2303       err |= __ios_base::eofbit;
2304       is.width(0);
2305     }
2306   }
2307   if (!extracted) {
2308     err |= __ios_base::failbit;
2309   }
2310   if (err) {
2311     is.setstate(err);
2312   }
2313   return is;
2314 }
2315
2316 template <typename E, class T, class A, class S>
2317 inline
2318 std::basic_ostream<typename basic_fbstring<E, T, A, S>::value_type,
2319                    typename basic_fbstring<E, T, A, S>::traits_type>&
2320 operator<<(
2321   std::basic_ostream<typename basic_fbstring<E, T, A, S>::value_type,
2322   typename basic_fbstring<E, T, A, S>::traits_type>& os,
2323     const basic_fbstring<E, T, A, S>& str) {
2324 #if _LIBCPP_VERSION
2325   typename std::basic_ostream<
2326     typename basic_fbstring<E, T, A, S>::value_type,
2327     typename basic_fbstring<E, T, A, S>::traits_type>::sentry __s(os);
2328   if (__s) {
2329     typedef std::ostreambuf_iterator<
2330       typename basic_fbstring<E, T, A, S>::value_type,
2331       typename basic_fbstring<E, T, A, S>::traits_type> _Ip;
2332     size_t __len = str.size();
2333     bool __left =
2334       (os.flags() & std::ios_base::adjustfield) == std::ios_base::left;
2335     if (__pad_and_output(_Ip(os),
2336                          str.data(),
2337                          __left ? str.data() + __len : str.data(),
2338                          str.data() + __len,
2339                          os,
2340                          os.fill()).failed()) {
2341       os.setstate(std::ios_base::badbit | std::ios_base::failbit);
2342     }
2343   }
2344 #else
2345   std::__ostream_insert(os, str.data(), str.size());
2346 #endif
2347   return os;
2348 }
2349
2350 #ifndef _LIBSTDCXX_FBSTRING
2351
2352 template <typename E, class T, class A, class S>
2353 inline
2354 std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2355                    typename basic_fbstring<E, T, A, S>::traits_type>&
2356 getline(
2357   std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2358   typename basic_fbstring<E, T, A, S>::traits_type>& is,
2359     basic_fbstring<E, T, A, S>& str,
2360   typename basic_fbstring<E, T, A, S>::value_type delim) {
2361   // Use the nonstandard getdelim()
2362   char * buf = nullptr;
2363   size_t size = 0;
2364   for (;;) {
2365     // This looks quadratic but it really depends on realloc
2366     auto const newSize = size + 128;
2367     buf = static_cast<char*>(checkedRealloc(buf, newSize));
2368     is.getline(buf + size, newSize - size, delim);
2369     if (is.bad() || is.eof() || !is.fail()) {
2370       // done by either failure, end of file, or normal read
2371       size += std::strlen(buf + size);
2372       break;
2373     }
2374     // Here we have failed due to too short a buffer
2375     // Minus one to discount the terminating '\0'
2376     size = newSize - 1;
2377     assert(buf[size] == 0);
2378     // Clear the error so we can continue reading
2379     is.clear();
2380   }
2381   basic_fbstring<E, T, A, S> result(buf, size, size + 1,
2382                                     AcquireMallocatedString());
2383   result.swap(str);
2384   return is;
2385 }
2386
2387 template <typename E, class T, class A, class S>
2388 inline
2389 std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2390                    typename basic_fbstring<E, T, A, S>::traits_type>&
2391 getline(
2392   std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
2393   typename basic_fbstring<E, T, A, S>::traits_type>& is,
2394   basic_fbstring<E, T, A, S>& str) {
2395   // Just forward to the version with a delimiter
2396   return getline(is, str, '\n');
2397 }
2398
2399 #endif
2400
2401 template <typename E1, class T, class A, class S>
2402 const typename basic_fbstring<E1, T, A, S>::size_type
2403 basic_fbstring<E1, T, A, S>::npos =
2404               static_cast<typename basic_fbstring<E1, T, A, S>::size_type>(-1);
2405
2406 #ifndef _LIBSTDCXX_FBSTRING
2407 // basic_string compatibility routines
2408
2409 template <typename E, class T, class A, class S>
2410 inline
2411 bool operator==(const basic_fbstring<E, T, A, S>& lhs,
2412                 const std::string& rhs) {
2413   return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) == 0;
2414 }
2415
2416 template <typename E, class T, class A, class S>
2417 inline
2418 bool operator==(const std::string& lhs,
2419                 const basic_fbstring<E, T, A, S>& rhs) {
2420   return rhs == lhs;
2421 }
2422
2423 template <typename E, class T, class A, class S>
2424 inline
2425 bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
2426                 const std::string& rhs) {
2427   return !(lhs == rhs);
2428 }
2429
2430 template <typename E, class T, class A, class S>
2431 inline
2432 bool operator!=(const std::string& lhs,
2433                 const basic_fbstring<E, T, A, S>& rhs) {
2434   return !(lhs == rhs);
2435 }
2436
2437 #if !defined(_LIBSTDCXX_FBSTRING)
2438 typedef basic_fbstring<char> fbstring;
2439 #endif
2440
2441 // fbstring is relocatable
2442 template <class T, class R, class A, class S>
2443 FOLLY_ASSUME_RELOCATABLE(basic_fbstring<T, R, A, S>);
2444
2445 #else
2446 _GLIBCXX_END_NAMESPACE_VERSION
2447 #endif
2448
2449 } // namespace folly
2450
2451 #ifndef _LIBSTDCXX_FBSTRING
2452
2453 // Hash functions to make fbstring usable with e.g. hash_map
2454 //
2455 // Handle interaction with different C++ standard libraries, which
2456 // expect these types to be in different namespaces.
2457 namespace std {
2458
2459 template <class C>
2460 struct hash<folly::basic_fbstring<C> > : private hash<const C*> {
2461   size_t operator()(const folly::basic_fbstring<C> & s) const {
2462     return hash<const C*>::operator()(s.c_str());
2463   }
2464 };
2465
2466 template <>
2467 struct hash< ::folly::fbstring> {
2468   size_t operator()(const ::folly::fbstring& s) const {
2469     return ::folly::hash::fnv32_buf(s.data(), s.size());
2470   }
2471 };
2472
2473 }
2474
2475 #if defined(_GLIBCXX_SYMVER) && !defined(__BIONIC__)
2476 namespace __gnu_cxx {
2477
2478 template <class C>
2479 struct hash<folly::basic_fbstring<C> > : private hash<const C*> {
2480   size_t operator()(const folly::basic_fbstring<C> & s) const {
2481     return hash<const C*>::operator()(s.c_str());
2482   }
2483 };
2484
2485 template <>
2486 struct hash< ::folly::fbstring> {
2487   size_t operator()(const ::folly::fbstring& s) const {
2488     return ::folly::hash::fnv32_buf(s.data(), s.size());
2489   }
2490 };
2491
2492 }
2493 #endif // _GLIBCXX_SYMVER && !__BIONIC__
2494 #endif // _LIBSTDCXX_FBSTRING
2495
2496 #pragma GCC diagnostic pop
2497
2498 #undef FBSTRING_DISABLE_ADDRESS_SANITIZER
2499 #undef throw
2500 #undef FBSTRING_LIKELY
2501 #undef FBSTRING_UNLIKELY
2502
2503 #endif // FOLLY_BASE_FBSTRING_H_