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