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