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