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