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