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