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