27 #include <type_traits> 33 #ifdef _LIBSTDCXX_FBSTRING 35 #pragma GCC system_header 37 #include <basic_fbstring_malloc.h> 40 #define FBSTRING_ASSERT(expr) 42 #else // !_LIBSTDCXX_FBSTRING 48 #if __has_include(<bits/c++config.h>) 49 #include <bits/c++config.h> 64 #define FBSTRING_ASSERT(expr) assert(expr) 70 #if defined(__GNUC__) && __GNUC__ >= 4 71 #define FBSTRING_LIKELY(x) (__builtin_expect((x), 1)) 72 #define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0)) 74 #define FBSTRING_LIKELY(x) (x) 75 #define FBSTRING_UNLIKELY(x) (x) 89 #define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW 91 #ifdef _LIBSTDCXX_FBSTRING 92 #define FOLLY_FBSTRING_BEGIN_NAMESPACE \ 93 namespace std _GLIBCXX_VISIBILITY(default) { \ 94 _GLIBCXX_BEGIN_NAMESPACE_VERSION 95 #define FOLLY_FBSTRING_END_NAMESPACE \ 96 _GLIBCXX_END_NAMESPACE_VERSION \ 99 #define FOLLY_FBSTRING_BEGIN_NAMESPACE namespace folly { 100 #define FOLLY_FBSTRING_END_NAMESPACE } // namespace folly 105 #if defined(__clang__) 106 #if __has_feature(address_sanitizer) 107 #define FBSTRING_SANITIZE_ADDRESS 109 #elif defined(__GNUC__) && \ 110 (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ >= 5)) && \ 112 #define FBSTRING_SANITIZE_ADDRESS 121 #ifdef FBSTRING_SANITIZE_ADDRESS 122 #define FBSTRING_DISABLE_SSO true 124 #define FBSTRING_DISABLE_SSO false 127 namespace fbstring_detail {
129 template <
class InIt,
class OutIt>
132 typename std::iterator_traits<InIt>::difference_type n,
134 for (; n != 0; --n, ++
b, ++d) {
137 return std::make_pair(b, d);
140 template <
class Pod,
class T>
143 constexpr
auto kUseMemset =
sizeof(
T) == 1;
145 memset(b, c,
size_t(e - b));
147 auto const ee = b + ((e -
b) & ~7u);
148 for (; b != ee; b += 8) {
159 for (; b != e; ++
b) {
174 inline void podCopy(
const Pod*
b,
const Pod* e, Pod* d) {
180 memcpy(d, b, (e - b) *
sizeof(Pod));
188 inline void podMove(
const Pod*
b,
const Pod* e, Pod* d) {
190 memmove(d, b, (e - b) *
sizeof(*b));
194 #if defined(__GNUC__) // Clang also defines __GNUC__ 195 #define FBSTRING_ALWAYS_INLINE inline __attribute__((__always_inline__)) 196 #elif defined(_MSC_VER) 197 #define FBSTRING_ALWAYS_INLINE __forceinline 199 #define FBSTRING_ALWAYS_INLINE inline 203 #if defined(__GNUC__) // Clang also defines __GNUC__ 204 __builtin_unreachable();
205 #elif defined(_MSC_VER) 326 template <
class Char>
331 #ifdef FOLLY_ENDIAN_BE 334 static constexpr
auto kIsLittleEndian =
true;
337 static constexpr
auto kIsLittleEndian =
338 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__;
348 case Category::isSmall:
351 case Category::isMedium:
354 case Category::isLarge:
375 if (!disableSSO && size <= maxSmallSize) {
376 initSmall(data, size);
377 }
else if (size <= maxMediumSize) {
378 initMedium(data, size);
380 initLarge(data, size);
384 size == 0 || memcmp(this->
data(), data, size *
sizeof(
Char)) == 0);
388 if (category() == Category::isSmall) {
391 destroyMediumLarge();
404 const size_t allocatedSize,
413 ml_.setCapacity(allocatedSize - 1, Category::isMedium);
437 switch (category()) {
438 case Category::isSmall:
440 case Category::isMedium:
442 case Category::isLarge:
443 return mutableDataLarge();
451 ptr = (category() == Category::isSmall) ? small_ : ptr;
456 if (category() == Category::isSmall) {
468 switch (category()) {
469 case Category::isSmall:
470 reserveSmall(minCapacity, disableSSO);
472 case Category::isMedium:
473 reserveMedium(minCapacity);
475 case Category::isLarge:
476 reserveLarge(minCapacity);
486 bool expGrowth =
false,
490 *expandNoinit(1,
true) =
c;
494 size_t ret = ml_.size_;
499 auto maybeSmallSize = size_t(maxSmallSize) -
500 size_t(static_cast<UChar>(small_[maxSmallSize]));
502 ret = (
static_cast<ssize_t
>(maybeSmallSize) >= 0) ? maybeSmallSize : ret;
504 ret = (category() == Category::isSmall) ? smallSize() : ret;
510 switch (category()) {
511 case Category::isSmall:
513 case Category::isLarge:
524 return ml_.capacity();
540 auto const c = category();
542 if (
c == Category::isMedium) {
545 RefCounted::decrementRefs(ml_.data_);
558 return static_cast<RefCounted*
>(
static_cast<void*
>(
559 static_cast<unsigned char*
>(
static_cast<void*
>(p)) -
564 return fromData(p)->refCount_.load(std::memory_order_acquire);
568 fromData(p)->refCount_.fetch_add(1, std::memory_order_acq_rel);
572 auto const dis = fromData(p);
573 size_t oldcnt = dis->refCount_.fetch_sub(1, std::memory_order_acq_rel);
581 const size_t allocSize =
584 result->
refCount_.store(1, std::memory_order_release);
585 *size = (allocSize - getDataOffset()) /
sizeof(
Char) - 1;
590 const size_t effectiveSize = *
size;
591 auto result = create(size);
600 const size_t currentSize,
601 const size_t currentCapacity,
602 size_t* newCapacity) {
604 const size_t allocNewCapacity =
606 auto const dis = fromData(data);
610 getDataOffset() + (currentSize + 1) *
sizeof(
Char),
611 getDataOffset() + (currentCapacity + 1) *
sizeof(
Char),
613 FBSTRING_ASSERT(result->refCount_.load(std::memory_order_acquire) == 1);
614 *newCapacity = (allocNewCapacity - getDataOffset()) /
sizeof(
Char) - 1;
623 isMedium = kIsLittleEndian ? 0x80 : 0x2,
624 isLarge = kIsLittleEndian ? 0x40 : 0x1,
629 return static_cast<Category>(bytes_[lastChar] & categoryExtractMask);
638 return kIsLittleEndian ? capacity_ & capacityExtractMask : capacity_ >> 2;
642 capacity_ = kIsLittleEndian
643 ? cap | (
static_cast<size_t>(
cat) << kCategoryShift)
644 : (cap << 2) | static_cast<size_t>(
cat);
654 constexpr
static size_t lastChar =
sizeof(MediumLarge) - 1;
655 constexpr
static size_t maxSmallSize = lastChar /
sizeof(
Char);
656 constexpr
static size_t maxMediumSize = 254 /
sizeof(
Char);
657 constexpr
static uint8_t categoryExtractMask = kIsLittleEndian ? 0xC0 : 0x3;
658 constexpr
static size_t kCategoryShift = (
sizeof(size_t) - 1) * 8;
659 constexpr
static size_t capacityExtractMask = kIsLittleEndian
660 ? ~(size_t(categoryExtractMask) << kCategoryShift)
664 !(
sizeof(MediumLarge) %
sizeof(
Char)),
665 "Corrupt memory layout for fbstring.");
669 constexpr
auto shift = kIsLittleEndian ? 0 : 2;
670 auto smallShifted =
static_cast<size_t>(small_[maxSmallSize]) >> shift;
672 return static_cast<size_t>(maxSmallSize) - smallShifted;
680 constexpr
auto shift = kIsLittleEndian ? 0 : 2;
681 small_[maxSmallSize] = char((maxSmallSize - s) << shift);
691 void initMedium(
const Char* data,
size_t size);
692 void initLarge(
const Char* data,
size_t size);
694 void reserveSmall(
size_t minCapacity,
bool disableSSO);
695 void reserveMedium(
size_t minCapacity);
696 void reserveLarge(
size_t minCapacity);
698 void shrinkSmall(
size_t delta);
699 void shrinkMedium(
size_t delta);
700 void shrinkLarge(
size_t delta);
702 void unshare(
size_t minCapacity = 0);
703 Char* mutableDataLarge();
706 template <
class Char>
708 static_assert(offsetof(
MediumLarge,
data_) == 0,
"fbstring layout failure");
711 "fbstring layout failure");
713 offsetof(
MediumLarge, capacity_) == 2 *
sizeof(ml_.data_),
714 "fbstring layout failure");
722 category() == Category::isSmall && this->
size() == rhs.
size());
725 template <
class Char>
736 ml_.setCapacity(allocSize /
sizeof(
Char) - 1, Category::isMedium);
740 template <
class Char>
745 RefCounted::incrementRefs(ml_.data_);
750 template <
class Char>
756 sizeof(*
this) ==
sizeof(
Char*) + 2 *
sizeof(
size_t),
757 "fbstring has unexpected size");
759 sizeof(
Char*) ==
sizeof(
size_t),
"fbstring size assumption violation");
762 (
sizeof(
size_t) & (
sizeof(
size_t) - 1)) == 0,
763 "fbstring size assumption violation");
770 #ifndef FBSTRING_SANITIZE_ADDRESS 771 if ((reinterpret_cast<size_t>(data) & (
sizeof(
size_t) - 1)) == 0) {
772 const size_t byteSize = size *
sizeof(
Char);
773 constexpr
size_t wordWidth =
sizeof(size_t);
774 switch ((byteSize + wordWidth - 1) / wordWidth) {
776 ml_.capacity_ =
reinterpret_cast<const size_t*
>(
data)[2];
779 ml_.size_ =
reinterpret_cast<const size_t*
>(
data)[1];
782 ml_.data_ = *
reinterpret_cast<Char**
>(
const_cast<Char*
>(
data));
797 template <
class Char>
809 ml_.setCapacity(allocSize /
sizeof(
Char) - 1, Category::isMedium);
810 ml_.data_[
size] =
'\0';
813 template <
class Char>
818 size_t effectiveCapacity =
size;
819 auto const newRC = RefCounted::create(data, &effectiveCapacity);
820 ml_.data_ = newRC->data_;
822 ml_.setCapacity(effectiveCapacity, Category::isLarge);
823 ml_.data_[
size] =
'\0';
826 template <
class Char>
828 size_t minCapacity) {
830 size_t effectiveCapacity =
std::max(minCapacity, ml_.capacity());
831 auto const newRC = RefCounted::create(&effectiveCapacity);
837 RefCounted::decrementRefs(ml_.data_);
838 ml_.data_ = newRC->data_;
839 ml_.setCapacity(effectiveCapacity, Category::isLarge);
843 template <
class Char>
852 template <
class Char>
854 size_t minCapacity) {
862 unshare(minCapacity);
865 if (minCapacity > ml_.capacity()) {
867 auto const newRC = RefCounted::reallocate(
868 ml_.data_, ml_.size_, ml_.capacity(), &minCapacity);
869 ml_.data_ = newRC->data_;
870 ml_.setCapacity(minCapacity, Category::isLarge);
876 template <
class Char>
878 const size_t minCapacity) {
881 if (minCapacity <= ml_.capacity()) {
884 if (minCapacity <= maxMediumSize) {
891 (ml_.size_ + 1) *
sizeof(
Char),
892 (ml_.capacity() + 1) *
sizeof(
Char),
894 ml_.setCapacity(capacityBytes /
sizeof(
Char) - 1, Category::isMedium);
903 ml_.data_, ml_.data_ + ml_.size_ + 1, nascent.
ml_.
data_);
909 template <
class Char>
912 const bool disableSSO) {
914 if (!disableSSO && minCapacity <= maxSmallSize) {
917 }
else if (minCapacity <= maxMediumSize) {
920 auto const allocSizeBytes =
923 auto const size = smallSize();
928 ml_.setCapacity(allocSizeBytes /
sizeof(
Char) - 1, Category::isMedium);
931 auto const newRC = RefCounted::create(&minCapacity);
932 auto const size = smallSize();
935 ml_.data_ = newRC->data_;
937 ml_.setCapacity(minCapacity, Category::isLarge);
942 template <
class Char>
950 if (category() == Category::isSmall) {
958 expGrowth ?
std::max(newSz, 2 * maxSmallSize) : newSz, disableSSO);
970 category() == Category::isMedium || category() == Category::isLarge);
972 ml_.data_[newSz] =
'\0';
974 return ml_.data_ + sz;
977 template <
class Char>
981 setSmallSize(smallSize() - delta);
984 template <
class Char>
990 ml_.data_[ml_.size_] =
'\0';
993 template <
class Char>
1005 #ifndef _LIBSTDCXX_FBSTRING 1010 template <
class Char>
1015 : backend_(another.backend_) {}
1021 return backend_.data();
1024 return const_cast<Char*
>(backend_.data());
1028 backend_.resize(
size() - delta);
1031 auto const sz =
size();
1032 backend_.resize(
size() + delta);
1033 return backend_.data() + sz;
1036 backend_.push_back(c);
1039 return backend_.size();
1042 return backend_.capacity();
1048 backend_.reserve(minCapacity);
1054 #endif // !_LIBSTDCXX_FBSTRING 1061 #ifdef _LIBSTDCXX_FBSTRING 1062 template <
typename E,
class T,
class A,
class Storage>
1066 class T = std::char_traits<E>,
1067 class A = std::allocator<E>,
1071 template <
typename Ex,
typename...
Args>
1074 throw_exception<Ex>(
static_cast<Args&&
>(args)...);
1081 capacity() <= max_size() &&
size() <= capacity() &&
1116 static constexpr size_type npos = size_type(-1);
1126 static size_type traitsLength(
const value_type*
s);
1151 : store_(
std::
move(goner.store_)) {}
1153 #ifndef _LIBSTDCXX_FBSTRING 1155 template <
typename A2>
1157 : store_(str.
data(), str.
size()) {}
1165 assign(str, pos, n);
1170 : store_(s, traitsLength(s)) {}
1178 auto const pData = store_.expandNoinit(n);
1182 template <
class InIt>
1186 typename std::enable_if<
1196 : store_(b, size_type(e - b)) {}
1204 : store_(s, n, c, a) {}
1209 assign(il.begin(), il.end());
1219 #ifndef _LIBSTDCXX_FBSTRING 1221 template <
typename A2>
1223 return assign(rhs.data(), rhs.size());
1228 return std::basic_string<E, T, A>(
data(),
size());
1252 template <
typename TP>
1253 typename std::enable_if<
1261 return assign(il.begin(), il.end());
1266 return store_.mutableData();
1270 return store_.data();
1278 return store_.mutableData() + store_.size();
1282 return store_.data() + store_.size();
1290 return reverse_iterator(
end());
1294 return const_reverse_iterator(
end());
1302 return reverse_iterator(
begin());
1305 const_reverse_iterator
rend()
const {
1306 return const_reverse_iterator(
begin());
1321 return *(
end() - 1);
1329 return *(
end() - 1);
1338 return store_.size();
1349 void resize(size_type n, value_type c = value_type());
1352 return store_.capacity();
1356 enforce<std::length_error>(res_arg <= max_size(),
"");
1357 store_.reserve(res_arg);
1362 if (capacity() <
size() * 3 / 2) {
1378 return *(
begin() + pos);
1382 return *(
begin() + pos);
1385 const_reference
at(size_type n)
const {
1386 enforce<std::out_of_range>(n <
size(),
"");
1390 reference
at(size_type n) {
1391 enforce<std::out_of_range>(n <
size(),
"");
1422 return append(s, traitsLength(s));
1427 template <
class InputIterator>
1429 insert(
end(), first, last);
1434 return append(il.begin(), il.end());
1438 store_.push_back(c);
1445 return assign(str.
data(), str.
size());
1453 assign(
const basic_fbstring& str,
const size_type pos, size_type n);
1458 return assign(s, traitsLength(s));
1462 return assign(il.begin(), il.end());
1465 template <
class ItOrLength,
class ItOrChar>
1471 return insert(pos1, str.
data(), str.
size());
1479 enforce<std::out_of_range>(pos2 <= str.
length(),
"");
1480 procrustes(n, str.
length() - pos2);
1481 return insert(pos1, str.
data() + pos2, n);
1485 enforce<std::out_of_range>(pos <= length(),
"");
1486 insert(
begin() + pos, s, s + n);
1491 return insert(pos, s, traitsLength(s));
1495 enforce<std::out_of_range>(pos <= length(),
"");
1496 insert(
begin() + pos, n, c);
1500 iterator
insert(const_iterator p,
const value_type c) {
1501 const size_type pos = p -
cbegin();
1503 return begin() + pos;
1506 #ifndef _LIBSTDCXX_FBSTRING 1509 istream_type& getlineImpl(istream_type& is, value_type delim);
1512 friend inline istream_type&
1518 return getline(is, str,
'\n');
1524 insertImplDiscr(const_iterator
i, size_type n, value_type c,
std::true_type);
1526 template <
class InputIter>
1528 insertImplDiscr(const_iterator i, InputIter b, InputIter e,
std::false_type);
1530 template <
class FwdIterator>
1531 iterator insertImpl(
1535 std::forward_iterator_tag);
1537 template <
class InputIterator>
1538 iterator insertImpl(
1542 std::input_iterator_tag);
1545 template <
class ItOrLength,
class ItOrChar>
1546 iterator
insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
1548 return insertImplDiscr(p, first_or_n, last_or_c, Sel());
1551 iterator
insert(const_iterator p, std::initializer_list<value_type> il) {
1552 return insert(p, il.begin(), il.end());
1556 Invariant checker(*
this);
1558 enforce<std::out_of_range>(pos <= length(),
"");
1559 procrustes(n, length() - pos);
1566 const size_type pos(position -
begin());
1567 enforce<std::out_of_range>(pos <=
size(),
"");
1569 return begin() + pos;
1573 const size_type pos(first -
begin());
1574 erase(pos, last - first);
1575 return begin() + pos;
1593 enforce<std::out_of_range>(pos2 <= str.
length(),
"");
1600 return replace(pos, n1, s, traitsLength(s));
1610 template <
class StrOrLength,
class NumOrChar>
1612 replace(size_type pos, size_type n1, StrOrLength s_or_n2, NumOrChar n_or_c) {
1613 Invariant checker(*
this);
1615 enforce<std::out_of_range>(pos <=
size(),
"");
1616 procrustes(n1, length() - pos);
1617 const iterator b =
begin() + pos;
1618 return replace(b, b + n1, s_or_n2, n_or_c);
1626 return replace(i1, i2, s, traitsLength(s));
1633 const value_type* s,
1635 std::integral_constant<int, 2>);
1642 std::integral_constant<int, 1>);
1644 template <
class InputIter>
1650 std::integral_constant<int, 0>);
1653 template <
class FwdIterator>
1663 template <
class FwdIterator>
1664 bool replaceAliased(
1671 template <
class FwdIterator>
1677 std::forward_iterator_tag);
1679 template <
class InputIterator>
1685 std::input_iterator_tag);
1688 template <
class T1,
class T2>
1690 replace(iterator i1, iterator i2,
T1 first_or_n_or_s,
T2 last_or_c_or_n) {
1691 constexpr
bool num1 = std::numeric_limits<T1>::is_specialized,
1692 num2 = std::numeric_limits<T2>::is_specialized;
1694 std::integral_constant<int, num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>;
1695 return replaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n, Sel());
1698 size_type
copy(value_type* s, size_type n, size_type pos = 0)
const {
1699 enforce<std::out_of_range>(pos <=
size(),
"");
1700 procrustes(n,
size() - pos);
1713 return store_.c_str();
1721 return allocator_type();
1728 size_type find(
const value_type*
needle, size_type pos, size_type nsize)
1731 size_type
find(
const value_type* s, size_type pos = 0)
const {
1732 return find(s, pos, traitsLength(s));
1735 size_type
find(value_type c, size_type pos = 0)
const {
1736 return find(&c, pos, 1);
1743 size_type
rfind(
const value_type* s, size_type pos, size_type n)
const;
1745 size_type
rfind(
const value_type* s, size_type pos = npos)
const {
1746 return rfind(s, pos, traitsLength(s));
1749 size_type
rfind(value_type c, size_type pos = npos)
const {
1750 return rfind(&c, pos, 1);
1754 return find_first_of(str.
data(), pos, str.
length());
1757 size_type find_first_of(
const value_type* s, size_type pos, size_type n)
1761 return find_first_of(s, pos, traitsLength(s));
1765 return find_first_of(&c, pos, 1);
1770 return find_last_of(str.
data(), pos, str.
length());
1773 size_type find_last_of(
const value_type* s, size_type pos, size_type n)
const;
1776 return find_last_of(s, pos, traitsLength(s));
1780 return find_last_of(&c, pos, 1);
1785 return find_first_not_of(str.
data(), pos, str.
size());
1788 size_type find_first_not_of(
const value_type* s, size_type pos, size_type n)
1792 return find_first_not_of(s, pos, traitsLength(s));
1796 return find_first_not_of(&c, pos, 1);
1801 return find_last_not_of(str.
data(), pos, str.
length());
1804 size_type find_last_not_of(
const value_type* s, size_type pos, size_type n)
1808 return find_last_not_of(s, pos, traitsLength(s));
1812 return find_last_not_of(&c, pos, 1);
1816 enforce<std::out_of_range>(pos <=
size(),
"");
1821 enforce<std::out_of_range>(pos <=
size(),
"");
1831 return compare(0,
size(), str);
1835 return compare(pos1, n1, str.
data(), str.
size());
1838 int compare(size_type pos1, size_type n1,
const value_type* s)
const {
1839 return compare(pos1, n1, s, traitsLength(s));
1842 int compare(size_type pos1, size_type n1,
const value_type* s, size_type n2)
1844 enforce<std::out_of_range>(pos1 <=
size(),
"");
1845 procrustes(n1,
size() - pos1);
1847 const int r = traits_type::compare(pos1 +
data(), s,
std::min(n1, n2));
1848 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
1856 size_type n2)
const {
1857 enforce<std::out_of_range>(pos2 <= str.
size(),
"");
1866 const size_type n1(
size()), n2(traitsLength(s));
1867 const int r = traits_type::compare(
data(), s,
std::min(n1, n2));
1868 return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
1876 template <
typename E,
class T,
class A,
class S>
1879 return s ? traits_type::length(s)
1880 : (throw_exception<std::logic_error>(
1881 "basic_fbstring: null pointer initializer not valid"),
1885 template <
typename E,
class T,
class A,
class S>
1894 return assign(lhs.
data(), lhs.
size());
1898 template <
typename E,
class T,
class A,
class S>
1909 new (&store_) S(
std::move(goner.store_));
1913 template <
typename E,
class T,
class A,
class S>
1914 template <
typename TP>
1915 inline typename std::enable_if<
1924 store_.expandNoinit(1);
1925 }
else if (store_.isShared()) {
1929 store_.shrink(
size() - 1);
1935 template <
typename E,
class T,
class A,
class S>
1938 const value_type c ) {
1943 store_.shrink(
size - n);
1945 auto const delta = n -
size;
1946 auto pData = store_.expandNoinit(delta);
1952 template <
typename E,
class T,
class A,
class S>
1956 auto desiredSize =
size() + str.
size();
1963 template <
typename E,
class T,
class A,
class S>
1966 const size_type pos,
1968 const size_type sz = str.
size();
1969 enforce<std::out_of_range>(pos <= sz,
"");
1970 procrustes(n, sz - pos);
1974 template <
typename E,
class T,
class A,
class S>
1983 auto const oldSize =
size();
1984 auto const oldData =
data();
1985 auto pData = store_.expandNoinit(n,
true);
1993 std::less_equal<const value_type*> le;
1997 s =
data() + (s - oldData);
2007 template <
typename E,
class T,
class A,
class S>
2012 auto pData = store_.expandNoinit(n,
true);
2017 template <
typename E,
class T,
class A,
class S>
2020 const size_type pos,
2022 const size_type sz = str.
size();
2023 enforce<std::out_of_range>(pos <= sz,
"");
2024 procrustes(n, sz - pos);
2025 return assign(str.
data() + pos, n);
2028 template <
typename E,
class T,
class A,
class S>
2035 }
else if (
size() >= n) {
2038 store_.shrink(
size() - n);
2053 #ifndef _LIBSTDCXX_FBSTRING 2054 template <
typename E,
class T,
class A,
class S>
2062 size_t avail = capacity() -
size;
2065 is.getline(store_.expandNoinit(avail), avail + 1, delim);
2066 size += is.gcount();
2068 if (is.bad() || is.eof() || !is.fail()) {
2070 if (!is.bad() && !is.eof()) {
2080 reserve(std::max<size_t>(63, 3 * size / 2));
2088 template <
typename E,
class T,
class A,
class S>
2091 const value_type*
needle,
2092 const size_type pos,
2093 const size_type nsize)
const {
2097 if (nsize + pos >
size || nsize + pos < pos) {
2106 auto const haystack =
data();
2107 auto const nsize_1 = nsize - 1;
2108 auto const lastNeedle = needle[nsize_1];
2115 const E*
i = haystack + pos;
2116 auto iEnd = haystack +
size - nsize_1;
2120 while (i[nsize_1] != lastNeedle) {
2128 for (
size_t j = 0;;) {
2130 if (i[j] != needle[j]) {
2135 while (skip <= nsize_1 && needle[nsize_1 - skip] != lastNeedle) {
2145 return i - haystack;
2152 template <
typename E,
class T,
class A,
class S>
2162 const size_type pos = i -
cbegin();
2164 auto oldSize =
size();
2165 store_.expandNoinit(n,
true);
2173 template <
typename E,
class T,
class A,
class S>
2174 template <
class InputIter>
2182 i, b, e,
typename std::iterator_traits<InputIter>::iterator_category());
2185 template <
typename E,
class T,
class A,
class S>
2186 template <
class FwdIterator>
2192 std::forward_iterator_tag) {
2196 const size_type pos = i -
cbegin();
2197 auto n = std::distance(s1, s2);
2200 auto oldSize =
size();
2201 store_.expandNoinit(n,
true);
2209 template <
typename E,
class T,
class A,
class S>
2210 template <
class InputIterator>
2216 std::input_iterator_tag) {
2217 const auto pos = i -
cbegin();
2219 for (; b != e; ++
b) {
2224 return begin() + pos;
2227 template <
typename E,
class T,
class A,
class S>
2231 const value_type* s,
2233 std::integral_constant<int, 2>) {
2237 return replace(i1, i2, s, s + n);
2240 template <
typename E,
class T,
class A,
class S>
2246 std::integral_constant<int, 1>) {
2247 const size_type n1 = i2 - i1;
2249 std::fill(i1, i1 + n2, c);
2252 std::fill(i1, i2, c);
2253 insert(i2, n2 - n1, c);
2259 template <
typename E,
class T,
class A,
class S>
2260 template <
class InputIter>
2266 std::integral_constant<int, 0>) {
2267 using Cat =
typename std::iterator_traits<InputIter>::iterator_category;
2268 replaceImpl(i1, i2, b, e, Cat());
2272 template <
typename E,
class T,
class A,
class S>
2273 template <
class FwdIterator>
2280 std::less_equal<const value_type*> le{};
2281 const bool aliased = le(&*
begin(), &*s1) && le(&*s1, &*
end());
2287 temp.
reserve(
size() - (i2 - i1) + std::distance(s1, s2));
2293 template <
typename E,
class T,
class A,
class S>
2294 template <
class FwdIterator>
2300 std::forward_iterator_tag) {
2307 if (replaceAliased(i1, i2, s1, s2, Sel())) {
2311 auto const n1 = i2 - i1;
2313 auto const n2 = std::distance(s1, s2);
2328 template <
typename E,
class T,
class A,
class S>
2329 template <
class InputIterator>
2335 std::input_iterator_tag) {
2341 template <
typename E,
class T,
class A,
class S>
2344 const value_type* s,
2346 size_type n)
const {
2355 const_iterator
i(
begin() + pos);
2357 if (traits_type::eq(*i, *s) && traits_type::compare(&*i, s, n) == 0) {
2367 template <
typename E,
class T,
class A,
class S>
2370 const value_type* s,
2372 size_type n)
const {
2373 if (pos > length() || n == 0) {
2376 const_iterator
i(
begin() + pos), finish(
end());
2377 for (;
i != finish; ++
i) {
2378 if (traits_type::find(s, n, *
i) !=
nullptr) {
2385 template <
typename E,
class T,
class A,
class S>
2388 const value_type* s,
2390 size_type n)
const {
2391 if (!
empty() && n > 0) {
2393 const_iterator
i(
begin() + pos);
2395 if (traits_type::find(s, n, *i) !=
nullptr) {
2406 template <
typename E,
class T,
class A,
class S>
2409 const value_type* s,
2411 size_type n)
const {
2412 if (pos < length()) {
2413 const_iterator
i(
begin() + pos), finish(
end());
2414 for (;
i != finish; ++
i) {
2415 if (traits_type::find(s, n, *
i) ==
nullptr) {
2423 template <
typename E,
class T,
class A,
class S>
2426 const value_type* s,
2428 size_type n)
const {
2429 if (!this->
empty()) {
2431 const_iterator
i(
begin() + pos);
2433 if (traits_type::find(s, n, *i) ==
nullptr) {
2446 template <
typename E,
class T,
class A,
class S>
2452 result.
append(lhs).append(rhs);
2457 template <
typename E,
class T,
class A,
class S>
2465 template <
typename E,
class T,
class A,
class S>
2474 auto const& rhsC =
rhs;
2479 template <
typename E,
class T,
class A,
class S>
2487 template <
typename E,
class T,
class A,
class S>
2495 result.
append(lhs, len).append(rhs);
2500 template <
typename E,
class T,
class A,
class S>
2508 rhs.insert(rhs.begin(), lhs, lhs + len);
2514 result.
append(lhs, len).append(rhs);
2519 template <
typename E,
class T,
class A,
class S>
2531 template <
typename E,
class T,
class A,
class S>
2538 rhs.insert(rhs.begin(), lhs);
2542 auto const& rhsC =
rhs;
2547 template <
typename E,
class T,
class A,
class S>
2555 const size_type len = traits_type::length(rhs);
2557 result.
append(lhs).append(rhs, len);
2562 template <
typename E,
class T,
class A,
class S>
2571 template <
typename E,
class T,
class A,
class S>
2583 template <
typename E,
class T,
class A,
class S>
2591 template <
typename E,
class T,
class A,
class S>
2598 template <
typename E,
class T,
class A,
class S>
2605 template <
typename E,
class T,
class A,
class S>
2612 template <
typename E,
class T,
class A,
class S>
2616 return !(lhs ==
rhs);
2619 template <
typename E,
class T,
class A,
class S>
2623 return !(lhs ==
rhs);
2626 template <
typename E,
class T,
class A,
class S>
2630 return !(lhs ==
rhs);
2633 template <
typename E,
class T,
class A,
class S>
2640 template <
typename E,
class T,
class A,
class S>
2647 template <
typename E,
class T,
class A,
class S>
2654 template <
typename E,
class T,
class A,
class S>
2661 template <
typename E,
class T,
class A,
class S>
2668 template <
typename E,
class T,
class A,
class S>
2675 template <
typename E,
class T,
class A,
class S>
2679 return !(rhs < lhs);
2682 template <
typename E,
class T,
class A,
class S>
2686 return !(rhs < lhs);
2689 template <
typename E,
class T,
class A,
class S>
2693 return !(rhs < lhs);
2696 template <
typename E,
class T,
class A,
class S>
2700 return !(lhs <
rhs);
2703 template <
typename E,
class T,
class A,
class S>
2707 return !(lhs <
rhs);
2710 template <
typename E,
class T,
class A,
class S>
2714 return !(lhs <
rhs);
2718 template <
typename E,
class T,
class A,
class S>
2724 template <
typename E,
class T,
class A,
class S>
2725 inline std::basic_istream<
2730 typename basic_fbstring<E, T, A, S>::value_type,
2733 typedef std::basic_istream<
2734 typename basic_fbstring<E, T, A, S>::value_type,
2737 typename _istream_type::sentry sentry(is);
2738 size_t extracted = 0;
2739 auto err = _istream_type::goodbit;
2741 auto n = is.width();
2746 for (
auto got = is.rdbuf()->sgetc(); extracted != size_t(n); ++extracted) {
2747 if (got == T::eof()) {
2748 err |= _istream_type::eofbit;
2756 got = is.rdbuf()->snextc();
2760 err |= _istream_type::failbit;
2768 template <
typename E,
class T,
class A,
class S>
2769 inline std::basic_ostream<
2770 typename basic_fbstring<E, T, A, S>::value_type,
2774 typename basic_fbstring<E, T, A, S>::value_type,
2778 typedef std::basic_ostream<
2779 typename basic_fbstring<E, T, A, S>::value_type,
2782 typename _ostream_type::sentry _s(os);
2784 typedef std::ostreambuf_iterator<
2785 typename basic_fbstring<E, T, A, S>::value_type,
2788 size_t __len = str.
size();
2790 (os.flags() & _ostream_type::adjustfield) == _ostream_type::left;
2791 if (__pad_and_output(
2794 __left ? str.
data() + __len : str.
data(),
2799 os.setstate(_ostream_type::badbit | _ostream_type::failbit);
2802 #elif defined(_MSC_VER) 2803 typedef decltype(os.precision()) streamsize;
2805 os.write(str.
data(),
static_cast<streamsize
>(str.
size()));
2807 std::__ostream_insert(os, str.
data(), str.
size());
2812 template <
typename E1,
class T,
class A,
class S>
2816 #ifndef _LIBSTDCXX_FBSTRING 2819 template <
typename E,
class T,
class A,
class S,
class A2>
2822 const std::basic_string<E, T, A2>& rhs) {
2823 return lhs.
compare(0, lhs.
size(), rhs.data(), rhs.size()) == 0;
2826 template <
typename E,
class T,
class A,
class S,
class A2>
2828 const std::basic_string<E, T, A2>& lhs,
2833 template <
typename E,
class T,
class A,
class S,
class A2>
2836 const std::basic_string<E, T, A2>& rhs) {
2837 return !(lhs ==
rhs);
2840 template <
typename E,
class T,
class A,
class S,
class A2>
2842 const std::basic_string<E, T, A2>& lhs,
2844 return !(lhs ==
rhs);
2847 template <
typename E,
class T,
class A,
class S,
class A2>
2850 const std::basic_string<E, T, A2>& rhs) {
2851 return lhs.
compare(0, lhs.
size(), rhs.data(), rhs.size()) < 0;
2854 template <
typename E,
class T,
class A,
class S,
class A2>
2857 const std::basic_string<E, T, A2>& rhs) {
2858 return lhs.
compare(0, lhs.
size(), rhs.data(), rhs.size()) > 0;
2861 template <
typename E,
class T,
class A,
class S,
class A2>
2863 const std::basic_string<E, T, A2>& lhs,
2868 template <
typename E,
class T,
class A,
class S,
class A2>
2870 const std::basic_string<E, T, A2>& lhs,
2875 template <
typename E,
class T,
class A,
class S,
class A2>
2878 const std::basic_string<E, T, A2>& rhs) {
2879 return !(lhs >
rhs);
2882 template <
typename E,
class T,
class A,
class S,
class A2>
2885 const std::basic_string<E, T, A2>& rhs) {
2886 return !(lhs <
rhs);
2889 template <
typename E,
class T,
class A,
class S,
class A2>
2891 const std::basic_string<E, T, A2>& lhs,
2893 return !(lhs >
rhs);
2896 template <
typename E,
class T,
class A,
class S,
class A2>
2898 const std::basic_string<E, T, A2>& lhs,
2900 return !(lhs <
rhs);
2903 #if !defined(_LIBSTDCXX_FBSTRING) 2908 template <
class T,
class R,
class A,
class S>
2915 #ifndef _LIBSTDCXX_FBSTRING 2922 #define FOLLY_FBSTRING_HASH1(T) \ 2924 struct hash<::folly::basic_fbstring<T>> { \ 2925 size_t operator()(const ::folly::basic_fbstring<T>& s) const { \ 2926 return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(T)); \ 2931 #define FOLLY_FBSTRING_HASH \ 2932 FOLLY_FBSTRING_HASH1(char) \ 2933 FOLLY_FBSTRING_HASH1(char16_t) \ 2934 FOLLY_FBSTRING_HASH1(char32_t) \ 2935 FOLLY_FBSTRING_HASH1(wchar_t) 2943 #undef FOLLY_FBSTRING_HASH 2944 #undef FOLLY_FBSTRING_HASH1 2946 #endif // _LIBSTDCXX_FBSTRING 2950 #undef FBSTRING_DISABLE_SSO 2951 #undef FBSTRING_SANITIZE_ADDRESS 2953 #undef FBSTRING_LIKELY 2954 #undef FBSTRING_UNLIKELY 2955 #undef FBSTRING_ASSERT 2957 #ifndef _LIBSTDCXX_FBSTRING void swap(fbstring_core &rhs)
std::reverse_iterator< iterator > reverse_iterator
size_type find_last_not_of(const basic_fbstring &str, size_type pos=npos) const
void reserve(size_t minCapacity)
const value_type * c_str() const
#define FOLLY_FBSTRING_BEGIN_NAMESPACE
void BENCHFUN() resize(size_t iters, size_t arg)
bool operator==(const char *c, CStringRange::Sentinel)
bool operator>(const std::basic_string< E, T, A2 > &lhs, const basic_fbstring< E, T, A, S > &rhs)
static void decrementRefs(Char *p)
traits_type::char_type value_type
std::basic_ostream< typename basic_fbstring< E, T, A, S >::value_type, typename basic_fbstring< E, T, A, S >::traits_type > & operator<<(std::basic_ostream< typename basic_fbstring< E, T, A, S >::value_type, typename basic_fbstring< E, T, A, S >::traits_type > &os, const basic_fbstring< E, T, A, S > &str)
#define FOLLY_GNU_DISABLE_WARNING(warningName)
void podMove(const Pod *b, const Pod *e, Pod *d)
basic_fbstring(const std::basic_string< E, T, A2 > &str)
basic_fbstring() noexcept
#define FOLLY_POP_WARNING
static size_t refs(Char *p)
void * checkedMalloc(size_t size)
#define FOLLY_ASSUME_RELOCATABLE(...)
basic_fbstring & replace(iterator i1, iterator i2, const value_type *s)
size_type max_size() const
~fbstring_core() noexcept
fbstring_core(const fbstring_core &rhs)
static void incrementRefs(Char *p)
friend istream_type & getline(istream_type &is, basic_fbstring &str, value_type delim)
int compare(size_type pos1, size_type n1, const basic_fbstring &str, size_type pos2, size_type n2) const
#define FOLLY_PUSH_WARNING
#define FOLLY_MALLOC_NOINLINE
#define FOLLY_ALWAYS_INLINE
basic_fbstring & erase(size_type pos=0, size_type n=npos)
iterator erase(iterator first, iterator last)
size_type find_first_not_of(value_type c, size_type pos=0) const
basic_fbstring(const basic_fbstring &str)
basic_fbstring & assign(const value_type *s)
basic_fbstring(const basic_fbstring &str, size_type pos, size_type n=npos, const A &=A())
const basic_fbstring & s_
std::basic_string< Char > backend_
#define FOLLY_FBSTRING_HASH
FOLLY_MALLOC_NOINLINE basic_fbstring(InIt begin, InIt end, typename std::enable_if< !std::is_same< InIt, value_type * >::value, const A >::type &=A())
iterator insert(const_iterator p, const value_type c)
static constexpr size_t getDataOffset()
fbstring_core(Char *const data, const size_t size, const size_t allocatedSize, AcquireMallocatedString)
constexpr detail::Map< Move > move
basic_fbstring(value_type *s, size_type n, size_type c, AcquireMallocatedString a)
FOLLY_MALLOC_NOINLINE basic_fbstring(const value_type *b, const value_type *e, const A &=A())
fbstring_core(const Char *const data, const size_t size, bool disableSSO=false)
static RefCounted * reallocate(Char *const data, const size_t currentSize, const size_t currentCapacity, size_t *newCapacity)
void podCopy(const Pod *b, const Pod *e, Pod *d)
const value_type & back() const
basic_fbstring< E, T, A, S > operator+(basic_fbstring< E, T, A, S > &&lhs, E rhs)
int compare(const value_type *s) const
const_iterator begin() const
size_type find_last_of(const basic_fbstring &str, size_type pos=npos) const
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
const Char * data() const
void BENCHFUN() getline(size_t iters, size_t arg)
auto begin(TestAdlIterable &instance)
#define FBSTRING_UNLIKELY(x)
std::reverse_iterator< const_iterator > const_reverse_iterator
const_reference operator[](size_type pos) const
std::unordered_map< std::string, IValidator * > refs
const_reverse_iterator crbegin() const
basic_fbstring(const A &) noexcept
const Char * data() const
constexpr auto kIsLittleEndian
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
std::basic_istream< value_type, traits_type > istream_type
basic_fbstring & operator=(const value_type *s)
detail::Skip skip(size_t count)
requires E e noexcept(noexcept(s.error(std::move(e))))
size_type rfind(value_type c, size_type pos=npos) const
FOLLY_MALLOC_NOINLINE basic_fbstring(std::initializer_list< value_type > il)
std::string toStdString(const folly::fbstring &s)
reference operator[](size_type pos)
bool_constant< true > true_type
basic_fbstring & operator+=(const value_type c)
basic_fbstring & replace(size_type pos1, size_type n1, const basic_fbstring &str, size_type pos2, size_type n2)
FOLLY_PUSH_WARNING RHS rhs
void setSmallSize(size_t s)
std::atomic< size_t > refCount_
FOLLY_MALLOC_NOINLINE basic_fbstring(const value_type *s, const A &=A())
iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c)
void reserve(size_type res_arg=0)
const value_type & front() const
size_type find_last_not_of(const value_type *s, size_type pos=npos) const
bool operator<=(const std::basic_string< E, T, A2 > &lhs, const basic_fbstring< E, T, A, S > &rhs)
void BENCHFUN() replace(size_t iters, size_t arg)
void BENCHFUN() push_back(size_t iters, size_t arg)
basic_fbstring & append(InputIterator first, InputIterator last)
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
static RefCounted * create(size_t *size)
void BENCHFUN() reserve(int iters, int size)
constexpr auto size(C const &c) -> decltype(c.size())
basic_fbstring & assign(basic_fbstring &&str)
int compare(const basic_fbstring &str) const
size_type find_first_of(const basic_fbstring &str, size_type pos=0) const
iterator erase(iterator position)
const value_type * data() const
#define FBSTRING_LIKELY(x)
bool replaceAliased(iterator, iterator, FwdIterator, FwdIterator, std::false_type)
reference at(size_type n)
basic_fbstring & append(const value_type *s)
constexpr auto empty(C const &c) -> decltype(c.empty())
FOLLY_MALLOC_NOINLINE basic_fbstring(const value_type *s, size_type n, const A &=A())
iterator insert(const_iterator p, std::initializer_list< value_type > il)
std::integral_constant< bool, B > bool_constant
~basic_fbstring() noexcept
basic_fbstring & insert(size_type pos1, const basic_fbstring &str, size_type pos2, size_type n)
size_type find_last_of(value_type c, size_type pos=npos) const
A::const_pointer const_pointer
basic_fbstring & replace(size_type pos, size_type n1, const value_type *s)
auto end(TestAdlIterable &instance)
static FOLLY_ALWAYS_INLINE void enforce(bool condition, Args &&...args)
size_type find_first_of(const value_type *s, size_type pos=0) const
Category category() const
size_t rfind(const Range< Iter > &haystack, const typename Range< Iter >::value_type &needle)
std::basic_string< E, T, A > toStdString() const
basic_fbstring & operator=(const std::basic_string< E, T, A2 > &rhs)
size_type find_last_not_of(value_type c, size_type pos=npos) const
basic_fbstring & insert(size_type pos, const value_type *s, size_type n)
static RefCounted * create(const Char *data, size_t *size)
size_type capacity() const
bool operator>=(const std::basic_string< E, T, A2 > &lhs, const basic_fbstring< E, T, A, S > &rhs)
basic_fbstring & insert(size_type pos1, const basic_fbstring &str)
A::difference_type difference_type
istream_type & getlineImpl(istream_type &is, value_type delim)
void swap(basic_fbstring &rhs)
static RefCounted * fromData(Char *p)
size_type rfind(const basic_fbstring &str, size_type pos=npos) const
static const char *const value
basic_fbstring substr(size_type pos=0, size_type n=npos)&&
dummy_fbstring_core(const Char *s, size_t n)
basic_fbstring & insert(size_type pos, const value_type *s)
basic_fbstring(basic_fbstring &&goner) noexcept
Char * expandNoinit(size_t delta)
size_type find(const basic_fbstring &str, size_type pos=0) const
int compare(size_type pos1, size_type n1, const value_type *s) const
void push_back(const value_type c)
basic_fbstring & operator=(std::initializer_list< value_type > il)
int compare(size_type pos1, size_type n1, const basic_fbstring &str) const
void shrink(size_t delta)
const_reference at(size_type n) const
A::const_reference const_reference
#define FBSTRING_ASSERT(expr)
size_type find(const value_type *s, size_type pos=0) const
#define FBSTRING_ALWAYS_INLINE
void setCapacity(size_t cap, Category cat)
Invariant(const basic_fbstring &s) noexcept
void shrink(const size_t delta)
const_reverse_iterator crend() const
std::pair< InIt, OutIt > copy_n(InIt b, typename std::iterator_traits< InIt >::difference_type n, OutIt d)
#define FOLLY_FBSTRING_END_NAMESPACE
const_reverse_iterator rend() const
const_iterator cend() const
fbstring_core(fbstring_core &&goner) noexcept
size_type find_first_not_of(const basic_fbstring &str, size_type pos=0) const
int compare(size_type pos1, size_type n1, const value_type *s, size_type n2) const
void assume_unreachable()
basic_fbstring & assign(const basic_fbstring &str)
void podFill(Pod *b, Pod *e, T c)
const_iterator end() const
size_type copy(value_type *s, size_type n, size_type pos=0) const
bool_constant< false > false_type
std::true_type IsRelocatable
#define FBSTRING_DISABLE_SSO
basic_fbstring & replace(size_type pos, size_type n1, StrOrLength s_or_n2, NumOrChar n_or_c)
void swap(basic_fbstring< E, T, A, S > &lhs, basic_fbstring< E, T, A, S > &rhs)
basic_fbstring & replace(size_type pos1, size_type n1, const basic_fbstring &str)
basic_fbstring & operator+=(std::initializer_list< value_type > il)
void * smartRealloc(void *p, const size_t currentSize, const size_t currentCapacity, const size_t newCapacity)
friend istream_type & getline(istream_type &is, basic_fbstring &str)
const_iterator cbegin() const
basic_fbstring & replace(iterator i1, iterator i2, T1 first_or_n_or_s, T2 last_or_c_or_n)
basic_fbstring & append(const basic_fbstring &str)
const_reverse_iterator rbegin() const
basic_fbstring< char > fbstring
const Char * c_str() const
reverse_iterator rbegin()
size_type find_last_of(const value_type *s, size_type pos=npos) const
basic_fbstring & append(std::initializer_list< value_type > il)
size_type find_first_of(value_type c, size_type pos=0) const
basic_fbstring & insert(size_type pos, size_type n, value_type c)
basic_fbstring & assign(std::initializer_list< value_type > il)
bool operator!=(const std::basic_string< E, T, A2 > &lhs, const basic_fbstring< E, T, A, S > &rhs)
basic_fbstring & operator+=(const basic_fbstring &str)
basic_fbstring substr(size_type pos=0, size_type n=npos) const &
size_type find_first_not_of(const value_type *s, size_type pos=0) const
static constexpr uint64_t data[1]
FOLLY_MALLOC_NOINLINE void destroyMediumLarge() noexcept
FOLLY_MALLOC_NOINLINE void reserve(size_t minCapacity, bool disableSSO=false)
dummy_fbstring_core(const dummy_fbstring_core &another)
basic_fbstring & assign(ItOrLength first_or_n, ItOrChar last_or_c)
void swap(dummy_fbstring_core &rhs)
size_type rfind(const value_type *s, size_type pos=npos) const
allocator_type get_allocator() const
static void procrustes(size_type &n, size_type nmax)
basic_fbstring & replace(iterator i1, iterator i2, const basic_fbstring &str)
Iterator< typename Container::const_iterator > cbegin(const Container &c)
#define FOLLY_FALLTHROUGH
std::basic_istream< typename basic_fbstring< E, T, A, S >::value_type, typename basic_fbstring< E, T, A, S >::traits_type > & operator>>(std::basic_istream< typename basic_fbstring< E, T, A, S >::value_type, typename basic_fbstring< E, T, A, S >::traits_type > &is, basic_fbstring< E, T, A, S > &str)
basic_fbstring & operator+=(const value_type *s)
FOLLY_MALLOC_NOINLINE basic_fbstring(size_type n, value_type c, const A &=A())
Iterator< typename Container::const_iterator > cend(const Container &c)
bool operator<(const std::basic_string< E, T, A2 > &lhs, const basic_fbstring< E, T, A, S > &rhs)
size_type find(value_type c, size_type pos=0) const
constexpr detail::First first
size_t goodMallocSize(size_t minSize) noexcept