Git Product home page Git Product logo

Comments (9)

christopherowen avatar christopherowen commented on May 31, 2024

perhaps this is relevant?

http://stackoverflow.com/questions/12920891/std-linker-error-with-apple-llvm-4-1

from folly.

christopherowen avatar christopherowen commented on May 31, 2024

this is the homebrew formula: https://github.com/mcuadros/homebrew-hhvm

from folly.

christopherowen avatar christopherowen commented on May 31, 2024

To get to this point, this patch needed to be applied:

mcuelenaere@e1655a6

from folly.

denji avatar denji commented on May 31, 2024

folly/folly/FBString.h

Lines 915 to 2427 in 32a9723

/**
* This is the basic_string replacement. For conformity,
* basic_fbstring takes the same template parameters, plus the last
* one which is the core.
*/
#ifdef _LIBSTDCXX_FBSTRING
template <typename E, class T, class A, class Storage>
#else
template <typename E,
class T = std::char_traits<E>,
class A = std::allocator<E>,
class Storage = fbstring_core<E> >
#endif
class basic_fbstring {
static void enforce(
bool condition,
void (*throw_exc)(const char*),
const char* msg) {
if (!condition) throw_exc(msg);
}
bool isSane() const {
return
begin() <= end() &&
empty() == (size() == 0) &&
empty() == (begin() == end()) &&
size() <= max_size() &&
capacity() <= max_size() &&
size() <= capacity() &&
begin()[size()] == '\0';
}
struct Invariant;
friend struct Invariant;
struct Invariant {
#ifndef NDEBUG
explicit Invariant(const basic_fbstring& s) : s_(s) {
assert(s_.isSane());
}
~Invariant() {
assert(s_.isSane());
}
private:
const basic_fbstring& s_;
#else
explicit Invariant(const basic_fbstring&) {}
#endif
Invariant& operator=(const Invariant&);
};
public:
// types
typedef T traits_type;
typedef typename traits_type::char_type value_type;
typedef A allocator_type;
typedef typename A::size_type size_type;
typedef typename A::difference_type difference_type;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef E* iterator;
typedef const E* const_iterator;
typedef std::reverse_iterator<iterator
#ifdef NO_ITERATOR_TRAITS
, value_type
#endif
> reverse_iterator;
typedef std::reverse_iterator<const_iterator
#ifdef NO_ITERATOR_TRAITS
, const value_type
#endif
> const_reverse_iterator;
static const size_type npos; // = size_type(-1)
private:
static void procrustes(size_type& n, size_type nmax) {
if (n > nmax) n = nmax;
}
public:
// C++11 21.4.2 construct/copy/destroy
explicit basic_fbstring(const A& a = A()) noexcept {
}
basic_fbstring(const basic_fbstring& str)
: store_(str.store_) {
}
// Move constructor
basic_fbstring(basic_fbstring&& goner) noexcept
: store_(std::move(goner.store_)) {
}
#ifndef _LIBSTDCXX_FBSTRING
// This is defined for compatibility with std::string
/* implicit */ basic_fbstring(const std::string& str)
: store_(str.data(), str.size()) {
}
#endif
basic_fbstring(const basic_fbstring& str, size_type pos,
size_type n = npos, const A& a = A()) {
assign(str, pos, n);
}
/* implicit */ basic_fbstring(const value_type* s, const A& a = A())
: store_(s, s
? traits_type::length(s)
: (std::__throw_logic_error(
"basic_fbstring: null pointer initializer not valid"),
0)) {
}
basic_fbstring(const value_type* s, size_type n, const A& a = A())
: store_(s, n) {
}
basic_fbstring(size_type n, value_type c, const A& a = A()) {
auto const data = store_.expand_noinit(n);
fbstring_detail::pod_fill(data, data + n, c);
store_.writeTerminator();
}
template <class InIt>
basic_fbstring(InIt begin, InIt end,
typename std::enable_if<
!std::is_same<typename std::remove_const<InIt>::type,
value_type*>::value, const A>::type & a = A()) {
assign(begin, end);
}
// Specialization for const char*, const char*
basic_fbstring(const value_type* b, const value_type* e)
: store_(b, e - b) {
}
// Nonstandard constructor
basic_fbstring(value_type *s, size_type n, size_type c,
AcquireMallocatedString a)
: store_(s, n, c, a) {
}
// Construction from initialization list
basic_fbstring(std::initializer_list<value_type> il) {
assign(il.begin(), il.end());
}
~basic_fbstring() noexcept {
}
basic_fbstring& operator=(const basic_fbstring& lhs) {
if (FBSTRING_UNLIKELY(&lhs == this)) {
return *this;
}
auto const oldSize = size();
auto const srcSize = lhs.size();
if (capacity() >= srcSize && !store_.isShared()) {
// great, just copy the contents
if (oldSize < srcSize)
store_.expand_noinit(srcSize - oldSize);
else
store_.shrink(oldSize - srcSize);
assert(size() == srcSize);
fbstring_detail::pod_copy(lhs.begin(), lhs.end(), begin());
store_.writeTerminator();
} else {
// need to reallocate, so we may as well create a brand new string
basic_fbstring(lhs).swap(*this);
}
return *this;
}
// Move assignment
basic_fbstring& operator=(basic_fbstring&& goner) noexcept {
if (FBSTRING_UNLIKELY(&goner == this)) {
// Compatibility with std::basic_string<>,
// C++11 21.4.2 [string.cons] / 23 requires self-move-assignment support.
return *this;
}
// No need of this anymore
this->~basic_fbstring();
// Move the goner into this
new(&store_) fbstring_core<E>(std::move(goner.store_));
return *this;
}
#ifndef _LIBSTDCXX_FBSTRING
// Compatibility with std::string
basic_fbstring & operator=(const std::string & rhs) {
return assign(rhs.data(), rhs.size());
}
// Compatibility with std::string
std::string toStdString() const {
return std::string(data(), size());
}
#else
// A lot of code in fbcode still uses this method, so keep it here for now.
const basic_fbstring& toStdString() const {
return *this;
}
#endif
basic_fbstring& operator=(const value_type* s) {
return assign(s);
}
basic_fbstring& operator=(value_type c) {
if (empty()) {
store_.expand_noinit(1);
} else if (store_.isShared()) {
basic_fbstring(1, c).swap(*this);
return *this;
} else {
store_.shrink(size() - 1);
}
*store_.mutable_data() = c;
store_.writeTerminator();
return *this;
}
basic_fbstring& operator=(std::initializer_list<value_type> il) {
return assign(il.begin(), il.end());
}
// C++11 21.4.3 iterators:
iterator begin() { return store_.mutable_data(); }
const_iterator begin() const { return store_.data(); }
const_iterator cbegin() const { return begin(); }
iterator end() {
return store_.mutable_data() + store_.size();
}
const_iterator end() const {
return store_.data() + store_.size();
}
const_iterator cend() const { return end(); }
reverse_iterator rbegin() {
return reverse_iterator(end());
}
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator crbegin() const { return rbegin(); }
reverse_iterator rend() {
return reverse_iterator(begin());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
const_reverse_iterator crend() const { return rend(); }
// Added by C++11
// C++11 21.4.5, element access:
const value_type& front() const { return *begin(); }
const value_type& back() const {
assert(!empty());
// Should be begin()[size() - 1], but that branches twice
return *(end() - 1);
}
value_type& front() { return *begin(); }
value_type& back() {
assert(!empty());
// Should be begin()[size() - 1], but that branches twice
return *(end() - 1);
}
void pop_back() {
assert(!empty());
store_.shrink(1);
}
// C++11 21.4.4 capacity:
size_type size() const { return store_.size(); }
size_type length() const { return size(); }
size_type max_size() const {
return std::numeric_limits<size_type>::max();
}
void resize(const size_type n, const value_type c = value_type()) {
auto size = this->size();
if (n <= size) {
store_.shrink(size - n);
} else {
// Do this in two steps to minimize slack memory copied (see
// smartRealloc).
auto const capacity = this->capacity();
assert(capacity >= size);
if (size < capacity) {
auto delta = std::min(n, capacity) - size;
store_.expand_noinit(delta);
fbstring_detail::pod_fill(begin() + size, end(), c);
size += delta;
if (size == n) {
store_.writeTerminator();
return;
}
assert(size < n);
}
auto const delta = n - size;
store_.expand_noinit(delta);
fbstring_detail::pod_fill(end() - delta, end(), c);
store_.writeTerminator();
}
assert(this->size() == n);
}
size_type capacity() const { return store_.capacity(); }
void reserve(size_type res_arg = 0) {
enforce(res_arg <= max_size(), std::__throw_length_error, "");
store_.reserve(res_arg);
}
void shrink_to_fit() {
// Shrink only if slack memory is sufficiently large
if (capacity() < size() * 3 / 2) {
return;
}
basic_fbstring(cbegin(), cend()).swap(*this);
}
void clear() { resize(0); }
bool empty() const { return size() == 0; }
// C++11 21.4.5 element access:
const_reference operator[](size_type pos) const {
return *(begin() + pos);
}
reference operator[](size_type pos) {
return *(begin() + pos);
}
const_reference at(size_type n) const {
enforce(n <= size(), std::__throw_out_of_range, "");
return (*this)[n];
}
reference at(size_type n) {
enforce(n < size(), std::__throw_out_of_range, "");
return (*this)[n];
}
// C++11 21.4.6 modifiers:
basic_fbstring& operator+=(const basic_fbstring& str) {
return append(str);
}
basic_fbstring& operator+=(const value_type* s) {
return append(s);
}
basic_fbstring& operator+=(const value_type c) {
push_back(c);
return *this;
}
basic_fbstring& operator+=(std::initializer_list<value_type> il) {
append(il);
return *this;
}
basic_fbstring& append(const basic_fbstring& str) {
#ifndef NDEBUG
auto desiredSize = size() + str.size();
#endif
append(str.data(), str.size());
assert(size() == desiredSize);
return *this;
}
basic_fbstring& append(const basic_fbstring& str, const size_type pos,
size_type n) {
const size_type sz = str.size();
enforce(pos <= sz, std::__throw_out_of_range, "");
procrustes(n, sz - pos);
return append(str.data() + pos, n);
}
basic_fbstring& append(const value_type* s, size_type n) {
#ifndef NDEBUG
Invariant checker(*this);
(void) checker;
#endif
if (FBSTRING_UNLIKELY(!n)) {
// Unlikely but must be done
return *this;
}
auto const oldSize = size();
auto const oldData = data();
// Check for aliasing (rare). We could use "<=" here but in theory
// those do not work for pointers unless the pointers point to
// elements in the same array. For that reason we use
// std::less_equal, which is guaranteed to offer a total order
// over pointers. See discussion at http://goo.gl/Cy2ya for more
// info.
std::less_equal<const value_type*> le;
if (FBSTRING_UNLIKELY(le(oldData, s) && !le(oldData + oldSize, s))) {
assert(le(s + n, oldData + oldSize));
const size_type offset = s - oldData;
store_.reserve(oldSize + n);
// Restore the source
s = data() + offset;
}
// Warning! Repeated appends with short strings may actually incur
// practically quadratic performance. Avoid that by pushing back
// the first character (which ensures exponential growth) and then
// appending the rest normally. Worst case the append may incur a
// second allocation but that will be rare.
push_back(*s++);
--n;
memcpy(store_.expand_noinit(n), s, n * sizeof(value_type));
assert(size() == oldSize + n + 1);
return *this;
}
basic_fbstring& append(const value_type* s) {
return append(s, traits_type::length(s));
}
basic_fbstring& append(size_type n, value_type c) {
resize(size() + n, c);
return *this;
}
template<class InputIterator>
basic_fbstring& append(InputIterator first, InputIterator last) {
insert(end(), first, last);
return *this;
}
basic_fbstring& append(std::initializer_list<value_type> il) {
return append(il.begin(), il.end());
}
void push_back(const value_type c) { // primitive
store_.push_back(c);
}
basic_fbstring& assign(const basic_fbstring& str) {
if (&str == this) return *this;
return assign(str.data(), str.size());
}
basic_fbstring& assign(basic_fbstring&& str) {
return *this = std::move(str);
}
basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
size_type n) {
const size_type sz = str.size();
enforce(pos <= sz, std::__throw_out_of_range, "");
procrustes(n, sz - pos);
return assign(str.data() + pos, n);
}
basic_fbstring& assign(const value_type* s, const size_type n) {
Invariant checker(*this);
(void) checker;
if (size() >= n) {
std::copy(s, s + n, begin());
resize(n);
assert(size() == n);
} else {
const value_type *const s2 = s + size();
std::copy(s, s2, begin());
append(s2, n - size());
assert(size() == n);
}
store_.writeTerminator();
assert(size() == n);
return *this;
}
basic_fbstring& assign(const value_type* s) {
return assign(s, traits_type::length(s));
}
basic_fbstring& assign(std::initializer_list<value_type> il) {
return assign(il.begin(), il.end());
}
template <class ItOrLength, class ItOrChar>
basic_fbstring& assign(ItOrLength first_or_n, ItOrChar last_or_c) {
return replace(begin(), end(), first_or_n, last_or_c);
}
basic_fbstring& insert(size_type pos1, const basic_fbstring& str) {
return insert(pos1, str.data(), str.size());
}
basic_fbstring& insert(size_type pos1, const basic_fbstring& str,
size_type pos2, size_type n) {
enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
procrustes(n, str.length() - pos2);
return insert(pos1, str.data() + pos2, n);
}
basic_fbstring& insert(size_type pos, const value_type* s, size_type n) {
enforce(pos <= length(), std::__throw_out_of_range, "");
insert(begin() + pos, s, s + n);
return *this;
}
basic_fbstring& insert(size_type pos, const value_type* s) {
return insert(pos, s, traits_type::length(s));
}
basic_fbstring& insert(size_type pos, size_type n, value_type c) {
enforce(pos <= length(), std::__throw_out_of_range, "");
insert(begin() + pos, n, c);
return *this;
}
iterator insert(const_iterator p, const value_type c) {
const size_type pos = p - begin();
insert(p, 1, c);
return begin() + pos;
}
private:
template <int i> class Selector {};
iterator insertImplDiscr(const_iterator p,
size_type n, value_type c, Selector<1>) {
Invariant checker(*this);
(void) checker;
auto const pos = p - begin();
assert(p >= begin() && p <= end());
if (capacity() - size() < n) {
const size_type sz = p - begin();
reserve(size() + n);
p = begin() + sz;
}
const iterator oldEnd = end();
if (n < size_type(oldEnd - p)) {
append(oldEnd - n, oldEnd);
//std::copy(
// reverse_iterator(oldEnd - n),
// reverse_iterator(p),
// reverse_iterator(oldEnd));
fbstring_detail::pod_move(&*p, &*oldEnd - n,
begin() + pos + n);
std::fill(begin() + pos, begin() + pos + n, c);
} else {
append(n - (end() - p), c);
append(iterator(p), oldEnd);
std::fill(iterator(p), oldEnd, c);
}
store_.writeTerminator();
return begin() + pos;
}
template<class InputIter>
iterator insertImplDiscr(const_iterator i,
InputIter b, InputIter e, Selector<0>) {
return insertImpl(i, b, e,
typename std::iterator_traits<InputIter>::iterator_category());
}
template <class FwdIterator>
iterator insertImpl(const_iterator i,
FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
Invariant checker(*this);
(void) checker;
const size_type pos = i - begin();
const typename std::iterator_traits<FwdIterator>::difference_type n2 =
std::distance(s1, s2);
assert(n2 >= 0);
using namespace fbstring_detail;
assert(pos <= size());
const typename std::iterator_traits<FwdIterator>::difference_type maxn2 =
capacity() - size();
if (maxn2 < n2) {
// realloc the string
reserve(size() + n2);
i = begin() + pos;
}
if (pos + n2 <= size()) {
const iterator tailBegin = end() - n2;
store_.expand_noinit(n2);
fbstring_detail::pod_copy(tailBegin, tailBegin + n2, end() - n2);
std::copy(const_reverse_iterator(tailBegin), const_reverse_iterator(i),
reverse_iterator(tailBegin + n2));
std::copy(s1, s2, begin() + pos);
} else {
FwdIterator t = s1;
const size_type old_size = size();
std::advance(t, old_size - pos);
const size_t newElems = std::distance(t, s2);
store_.expand_noinit(n2);
std::copy(t, s2, begin() + old_size);
fbstring_detail::pod_copy(data() + pos, data() + old_size,
begin() + old_size + newElems);
std::copy(s1, t, begin() + pos);
}
store_.writeTerminator();
return begin() + pos;
}
template <class InputIterator>
iterator insertImpl(const_iterator i,
InputIterator b, InputIterator e,
std::input_iterator_tag) {
const auto pos = i - begin();
basic_fbstring temp(begin(), i);
for (; b != e; ++b) {
temp.push_back(*b);
}
temp.append(i, cend());
swap(temp);
return begin() + pos;
}
public:
template <class ItOrLength, class ItOrChar>
iterator insert(const_iterator p, ItOrLength first_or_n, ItOrChar last_or_c) {
Selector<std::numeric_limits<ItOrLength>::is_specialized> sel;
return insertImplDiscr(p, first_or_n, last_or_c, sel);
}
iterator insert(const_iterator p, std::initializer_list<value_type> il) {
return insert(p, il.begin(), il.end());
}
basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
Invariant checker(*this);
(void) checker;
enforce(pos <= length(), std::__throw_out_of_range, "");
procrustes(n, length() - pos);
std::copy(begin() + pos + n, end(), begin() + pos);
resize(length() - n);
return *this;
}
iterator erase(iterator position) {
const size_type pos(position - begin());
enforce(pos <= size(), std::__throw_out_of_range, "");
erase(pos, 1);
return begin() + pos;
}
iterator erase(iterator first, iterator last) {
const size_type pos(first - begin());
erase(pos, last - first);
return begin() + pos;
}
// Replaces at most n1 chars of *this, starting with pos1 with the
// content of str
basic_fbstring& replace(size_type pos1, size_type n1,
const basic_fbstring& str) {
return replace(pos1, n1, str.data(), str.size());
}
// Replaces at most n1 chars of *this, starting with pos1,
// with at most n2 chars of str starting with pos2
basic_fbstring& replace(size_type pos1, size_type n1,
const basic_fbstring& str,
size_type pos2, size_type n2) {
enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
return replace(pos1, n1, str.data() + pos2,
std::min(n2, str.size() - pos2));
}
// Replaces at most n1 chars of *this, starting with pos, with chars from s
basic_fbstring& replace(size_type pos, size_type n1, const value_type* s) {
return replace(pos, n1, s, traits_type::length(s));
}
// Replaces at most n1 chars of *this, starting with pos, with n2
// occurrences of c
//
// consolidated with
//
// Replaces at most n1 chars of *this, starting with pos, with at
// most n2 chars of str. str must have at least n2 chars.
template <class StrOrLength, class NumOrChar>
basic_fbstring& replace(size_type pos, size_type n1,
StrOrLength s_or_n2, NumOrChar n_or_c) {
Invariant checker(*this);
(void) checker;
enforce(pos <= size(), std::__throw_out_of_range, "");
procrustes(n1, length() - pos);
const iterator b = begin() + pos;
return replace(b, b + n1, s_or_n2, n_or_c);
}
basic_fbstring& replace(iterator i1, iterator i2, const basic_fbstring& str) {
return replace(i1, i2, str.data(), str.length());
}
basic_fbstring& replace(iterator i1, iterator i2, const value_type* s) {
return replace(i1, i2, s, traits_type::length(s));
}
private:
basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
const value_type* s, size_type n,
Selector<2>) {
assert(i1 <= i2);
assert(begin() <= i1 && i1 <= end());
assert(begin() <= i2 && i2 <= end());
return replace(i1, i2, s, s + n);
}
basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
size_type n2, value_type c, Selector<1>) {
const size_type n1 = i2 - i1;
if (n1 > n2) {
std::fill(i1, i1 + n2, c);
erase(i1 + n2, i2);
} else {
std::fill(i1, i2, c);
insert(i2, n2 - n1, c);
}
assert(isSane());
return *this;
}
template <class InputIter>
basic_fbstring& replaceImplDiscr(iterator i1, iterator i2,
InputIter b, InputIter e,
Selector<0>) {
replaceImpl(i1, i2, b, e,
typename std::iterator_traits<InputIter>::iterator_category());
return *this;
}
private:
template <class FwdIterator>
bool replaceAliased(iterator i1, iterator i2,
FwdIterator s1, FwdIterator s2, std::false_type) {
return false;
}
template <class FwdIterator>
bool replaceAliased(iterator i1, iterator i2,
FwdIterator s1, FwdIterator s2, std::true_type) {
static const std::less_equal<const value_type*> le =
std::less_equal<const value_type*>();
const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
if (!aliased) {
return false;
}
// Aliased replace, copy to new string
basic_fbstring temp;
temp.reserve(size() - (i2 - i1) + std::distance(s1, s2));
temp.append(begin(), i1).append(s1, s2).append(i2, end());
swap(temp);
return true;
}
template <class FwdIterator>
void replaceImpl(iterator i1, iterator i2,
FwdIterator s1, FwdIterator s2, std::forward_iterator_tag) {
Invariant checker(*this);
(void) checker;
// Handle aliased replace
if (replaceAliased(i1, i2, s1, s2,
std::integral_constant<bool,
std::is_same<FwdIterator, iterator>::value ||
std::is_same<FwdIterator, const_iterator>::value>())) {
return;
}
auto const n1 = i2 - i1;
assert(n1 >= 0);
auto const n2 = std::distance(s1, s2);
assert(n2 >= 0);
if (n1 > n2) {
// shrinks
std::copy(s1, s2, i1);
erase(i1 + n2, i2);
} else {
// grows
fbstring_detail::copy_n(s1, n1, i1);
std::advance(s1, n1);
insert(i2, s1, s2);
}
assert(isSane());
}
template <class InputIterator>
void replaceImpl(iterator i1, iterator i2,
InputIterator b, InputIterator e, std::input_iterator_tag) {
basic_fbstring temp(begin(), i1);
temp.append(b, e).append(i2, end());
swap(temp);
}
public:
template <class T1, class T2>
basic_fbstring& replace(iterator i1, iterator i2,
T1 first_or_n_or_s, T2 last_or_c_or_n) {
const bool
num1 = std::numeric_limits<T1>::is_specialized,
num2 = std::numeric_limits<T2>::is_specialized;
return replaceImplDiscr(
i1, i2, first_or_n_or_s, last_or_c_or_n,
Selector<num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>());
}
size_type copy(value_type* s, size_type n, size_type pos = 0) const {
enforce(pos <= size(), std::__throw_out_of_range, "");
procrustes(n, size() - pos);
fbstring_detail::pod_copy(
data() + pos,
data() + pos + n,
s);
return n;
}
void swap(basic_fbstring& rhs) {
store_.swap(rhs.store_);
}
const value_type* c_str() const {
return store_.c_str();
}
const value_type* data() const { return c_str(); }
allocator_type get_allocator() const {
return allocator_type();
}
size_type find(const basic_fbstring& str, size_type pos = 0) const {
return find(str.data(), pos, str.length());
}
size_type find(const value_type* needle, const size_type pos,
const size_type nsize) const {
if (!nsize) return pos;
auto const size = this->size();
// nsize + pos can overflow (eg pos == npos), guard against that by checking
// that nsize + pos does not wrap around.
if (nsize + pos > size || nsize + pos < pos) return npos;
// Don't use std::search, use a Boyer-Moore-like trick by comparing
// the last characters first
auto const haystack = data();
auto const nsize_1 = nsize - 1;
auto const lastNeedle = needle[nsize_1];
// Boyer-Moore skip value for the last char in the needle. Zero is
// not a valid value; skip will be computed the first time it's
// needed.
size_type skip = 0;
const E * i = haystack + pos;
auto iEnd = haystack + size - nsize_1;
while (i < iEnd) {
// Boyer-Moore: match the last element in the needle
while (i[nsize_1] != lastNeedle) {
if (++i == iEnd) {
// not found
return npos;
}
}
// Here we know that the last char matches
// Continue in pedestrian mode
for (size_t j = 0; ; ) {
assert(j < nsize);
if (i[j] != needle[j]) {
// Not found, we can skip
// Compute the skip value lazily
if (skip == 0) {
skip = 1;
while (skip <= nsize_1 && needle[nsize_1 - skip] != lastNeedle) {
++skip;
}
}
i += skip;
break;
}
// Check if done searching
if (++j == nsize) {
// Yay
return i - haystack;
}
}
}
return npos;
}
size_type find(const value_type* s, size_type pos = 0) const {
return find(s, pos, traits_type::length(s));
}
size_type find (value_type c, size_type pos = 0) const {
return find(&c, pos, 1);
}
size_type rfind(const basic_fbstring& str, size_type pos = npos) const {
return rfind(str.data(), pos, str.length());
}
size_type rfind(const value_type* s, size_type pos, size_type n) const {
if (n > length()) return npos;
pos = std::min(pos, length() - n);
if (n == 0) return pos;
const_iterator i(begin() + pos);
for (; ; --i) {
if (traits_type::eq(*i, *s)
&& traits_type::compare(&*i, s, n) == 0) {
return i - begin();
}
if (i == begin()) break;
}
return npos;
}
size_type rfind(const value_type* s, size_type pos = npos) const {
return rfind(s, pos, traits_type::length(s));
}
size_type rfind(value_type c, size_type pos = npos) const {
return rfind(&c, pos, 1);
}
size_type find_first_of(const basic_fbstring& str, size_type pos = 0) const {
return find_first_of(str.data(), pos, str.length());
}
size_type find_first_of(const value_type* s,
size_type pos, size_type n) const {
if (pos > length() || n == 0) return npos;
const_iterator i(begin() + pos),
finish(end());
for (; i != finish; ++i) {
if (traits_type::find(s, n, *i) != 0) {
return i - begin();
}
}
return npos;
}
size_type find_first_of(const value_type* s, size_type pos = 0) const {
return find_first_of(s, pos, traits_type::length(s));
}
size_type find_first_of(value_type c, size_type pos = 0) const {
return find_first_of(&c, pos, 1);
}
size_type find_last_of (const basic_fbstring& str,
size_type pos = npos) const {
return find_last_of(str.data(), pos, str.length());
}
size_type find_last_of (const value_type* s, size_type pos,
size_type n) const {
if (!empty() && n > 0) {
pos = std::min(pos, length() - 1);
const_iterator i(begin() + pos);
for (;; --i) {
if (traits_type::find(s, n, *i) != 0) {
return i - begin();
}
if (i == begin()) break;
}
}
return npos;
}
size_type find_last_of (const value_type* s,
size_type pos = npos) const {
return find_last_of(s, pos, traits_type::length(s));
}
size_type find_last_of (value_type c, size_type pos = npos) const {
return find_last_of(&c, pos, 1);
}
size_type find_first_not_of(const basic_fbstring& str,
size_type pos = 0) const {
return find_first_not_of(str.data(), pos, str.size());
}
size_type find_first_not_of(const value_type* s, size_type pos,
size_type n) const {
if (pos < length()) {
const_iterator
i(begin() + pos),
finish(end());
for (; i != finish; ++i) {
if (traits_type::find(s, n, *i) == 0) {
return i - begin();
}
}
}
return npos;
}
size_type find_first_not_of(const value_type* s,
size_type pos = 0) const {
return find_first_not_of(s, pos, traits_type::length(s));
}
size_type find_first_not_of(value_type c, size_type pos = 0) const {
return find_first_not_of(&c, pos, 1);
}
size_type find_last_not_of(const basic_fbstring& str,
size_type pos = npos) const {
return find_last_not_of(str.data(), pos, str.length());
}
size_type find_last_not_of(const value_type* s, size_type pos,
size_type n) const {
if (!this->empty()) {
pos = std::min(pos, size() - 1);
const_iterator i(begin() + pos);
for (;; --i) {
if (traits_type::find(s, n, *i) == 0) {
return i - begin();
}
if (i == begin()) break;
}
}
return npos;
}
size_type find_last_not_of(const value_type* s,
size_type pos = npos) const {
return find_last_not_of(s, pos, traits_type::length(s));
}
size_type find_last_not_of (value_type c, size_type pos = npos) const {
return find_last_not_of(&c, pos, 1);
}
basic_fbstring substr(size_type pos = 0, size_type n = npos) const {
enforce(pos <= size(), std::__throw_out_of_range, "");
return basic_fbstring(data() + pos, std::min(n, size() - pos));
}
int compare(const basic_fbstring& str) const {
// FIX due to Goncalo N M de Carvalho July 18, 2005
return compare(0, size(), str);
}
int compare(size_type pos1, size_type n1,
const basic_fbstring& str) const {
return compare(pos1, n1, str.data(), str.size());
}
int compare(size_type pos1, size_type n1,
const value_type* s) const {
return compare(pos1, n1, s, traits_type::length(s));
}
int compare(size_type pos1, size_type n1,
const value_type* s, size_type n2) const {
enforce(pos1 <= size(), std::__throw_out_of_range, "");
procrustes(n1, size() - pos1);
// The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
}
int compare(size_type pos1, size_type n1,
const basic_fbstring& str,
size_type pos2, size_type n2) const {
enforce(pos2 <= str.size(), std::__throw_out_of_range, "");
return compare(pos1, n1, str.data() + pos2,
std::min(n2, str.size() - pos2));
}
// Code from Jean-Francois Bastien (03/26/2007)
int compare(const value_type* s) const {
// Could forward to compare(0, size(), s, traits_type::length(s))
// but that does two extra checks
const size_type n1(size()), n2(traits_type::length(s));
const int r = traits_type::compare(data(), s, std::min(n1, n2));
return r != 0 ? r : n1 > n2 ? 1 : n1 < n2 ? -1 : 0;
}
private:
// Data
Storage store_;
};
// non-member functions
// C++11 21.4.8.1/2
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
basic_fbstring<E, T, A, S> result;
result.reserve(lhs.size() + rhs.size());
result.append(lhs).append(rhs);
return std::move(result);
}
// C++11 21.4.8.1/2
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return std::move(lhs.append(rhs));
}
// C++11 21.4.8.1/3
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(const basic_fbstring<E, T, A, S>& lhs,
basic_fbstring<E, T, A, S>&& rhs) {
if (rhs.capacity() >= lhs.size() + rhs.size()) {
// Good, at least we don't need to reallocate
return std::move(rhs.insert(0, lhs));
}
// Meh, no go. Forward to operator+(const&, const&).
auto const& rhsC = rhs;
return lhs + rhsC;
}
// C++11 21.4.8.1/4
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
basic_fbstring<E, T, A, S>&& rhs) {
return std::move(lhs.append(rhs));
}
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(
const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
//
basic_fbstring<E, T, A, S> result;
const typename basic_fbstring<E, T, A, S>::size_type len =
basic_fbstring<E, T, A, S>::traits_type::length(lhs);
result.reserve(len + rhs.size());
result.append(lhs, len).append(rhs);
return result;
}
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(
typename basic_fbstring<E, T, A, S>::value_type lhs,
const basic_fbstring<E, T, A, S>& rhs) {
basic_fbstring<E, T, A, S> result;
result.reserve(1 + rhs.size());
result.push_back(lhs);
result.append(rhs);
return result;
}
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(
const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
typedef typename basic_fbstring<E, T, A, S>::size_type size_type;
typedef typename basic_fbstring<E, T, A, S>::traits_type traits_type;
basic_fbstring<E, T, A, S> result;
const size_type len = traits_type::length(rhs);
result.reserve(lhs.size() + len);
result.append(lhs).append(rhs, len);
return result;
}
template <typename E, class T, class A, class S>
inline
basic_fbstring<E, T, A, S> operator+(
const basic_fbstring<E, T, A, S>& lhs,
typename basic_fbstring<E, T, A, S>::value_type rhs) {
basic_fbstring<E, T, A, S> result;
result.reserve(lhs.size() + 1);
result.append(lhs);
result.push_back(rhs);
return result;
}
template <typename E, class T, class A, class S>
inline
bool operator==(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; }
template <typename E, class T, class A, class S>
inline
bool operator==(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs == lhs; }
template <typename E, class T, class A, class S>
inline
bool operator==(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return lhs.compare(rhs) == 0; }
template <typename E, class T, class A, class S>
inline
bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs == rhs); }
template <typename E, class T, class A, class S>
inline
bool operator!=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs == rhs); }
template <typename E, class T, class A, class S>
inline
bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return !(lhs == rhs); }
template <typename E, class T, class A, class S>
inline
bool operator<(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return lhs.compare(rhs) < 0; }
template <typename E, class T, class A, class S>
inline
bool operator<(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return lhs.compare(rhs) < 0; }
template <typename E, class T, class A, class S>
inline
bool operator<(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs.compare(lhs) > 0; }
template <typename E, class T, class A, class S>
inline
bool operator>(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs < lhs; }
template <typename E, class T, class A, class S>
inline
bool operator>(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return rhs < lhs; }
template <typename E, class T, class A, class S>
inline
bool operator>(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs < lhs; }
template <typename E, class T, class A, class S>
inline
bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(rhs < lhs); }
template <typename E, class T, class A, class S>
inline
bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return !(rhs < lhs); }
template <typename E, class T, class A, class S>
inline
bool operator<=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(rhs < lhs); }
template <typename E, class T, class A, class S>
inline
bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs < rhs); }
template <typename E, class T, class A, class S>
inline
bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
const typename basic_fbstring<E, T, A, S>::value_type* rhs) {
return !(lhs < rhs); }
template <typename E, class T, class A, class S>
inline
bool operator>=(const typename basic_fbstring<E, T, A, S>::value_type* lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs < rhs);
}
// C++11 21.4.8.8
template <typename E, class T, class A, class S>
void swap(basic_fbstring<E, T, A, S>& lhs, basic_fbstring<E, T, A, S>& rhs) {
lhs.swap(rhs);
}
// TODO: make this faster.
template <typename E, class T, class A, class S>
inline
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) {
typename std::basic_istream<E, T>::sentry sentry(is);
typedef std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type>
__istream_type;
typedef typename __istream_type::ios_base __ios_base;
size_t extracted = 0;
auto err = __ios_base::goodbit;
if (sentry) {
auto n = is.width();
if (n == 0) {
n = str.max_size();
}
str.erase();
auto got = is.rdbuf()->sgetc();
for (; extracted != n && got != T::eof() && !isspace(got); ++extracted) {
// Whew. We get to store this guy
str.push_back(got);
got = is.rdbuf()->snextc();
}
if (got == T::eof()) {
err |= __ios_base::eofbit;
is.width(0);
}
}
if (!extracted) {
err |= __ios_base::failbit;
}
if (err) {
is.setstate(err);
}
return is;
}
template <typename E, class T, class A, class S>
inline
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) {
#if _LIBCPP_VERSION
typename std::basic_ostream<
typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type>::sentry __s(os);
if (__s) {
typedef std::ostreambuf_iterator<
typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type> _Ip;
size_t __len = str.size();
bool __left =
(os.flags() & std::ios_base::adjustfield) == std::ios_base::left;
if (__pad_and_output(_Ip(os),
str.data(),
__left ? str.data() + __len : str.data(),
str.data() + __len,
os,
os.fill()).failed()) {
os.setstate(std::ios_base::badbit | std::ios_base::failbit);
}
}
#else
std::__ostream_insert(os, str.data(), str.size());
#endif
return os;
}
#ifndef _LIBSTDCXX_FBSTRING
template <typename E, class T, class A, class S>
inline
std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type>&
getline(
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,
typename basic_fbstring<E, T, A, S>::value_type delim) {
// Use the nonstandard getdelim()
char * buf = nullptr;
size_t size = 0;
for (;;) {
// This looks quadratic but it really depends on realloc
auto const newSize = size + 128;
buf = static_cast<char*>(checkedRealloc(buf, newSize));
is.getline(buf + size, newSize - size, delim);
if (is.bad() || is.eof() || !is.fail()) {
// done by either failure, end of file, or normal read
size += std::strlen(buf + size);
break;
}
// Here we have failed due to too short a buffer
// Minus one to discount the terminating '\0'
size = newSize - 1;
assert(buf[size] == 0);
// Clear the error so we can continue reading
is.clear();
}
basic_fbstring<E, T, A, S> result(buf, size, size + 1,
AcquireMallocatedString());
result.swap(str);
return is;
}
template <typename E, class T, class A, class S>
inline
std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type>&
getline(
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) {
// Just forward to the version with a delimiter
return getline(is, str, '\n');
}
#endif
template <typename E1, class T, class A, class S>
const typename basic_fbstring<E1, T, A, S>::size_type
basic_fbstring<E1, T, A, S>::npos =
static_cast<typename basic_fbstring<E1, T, A, S>::size_type>(-1);
#ifndef _LIBSTDCXX_FBSTRING
// basic_string compatibility routines
template <typename E, class T, class A, class S>
inline
bool operator==(const basic_fbstring<E, T, A, S>& lhs,
const std::string& rhs) {
return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) == 0;
}
template <typename E, class T, class A, class S>
inline
bool operator==(const std::string& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs == lhs;
}
template <typename E, class T, class A, class S>
inline
bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
const std::string& rhs) {
return !(lhs == rhs);
}
template <typename E, class T, class A, class S>
inline
bool operator!=(const std::string& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs == rhs);
}
#if !defined(_LIBSTDCXX_FBSTRING)
typedef basic_fbstring<char> fbstring;
#endif
// fbstring is relocatable
template <class T, class R, class A, class S>
FOLLY_ASSUME_RELOCATABLE(basic_fbstring<T, R, A, S>);
#else
_GLIBCXX_END_NAMESPACE_VERSION
#endif
} // namespace folly
#ifndef _LIBSTDCXX_FBSTRING
// Hash functions to make fbstring usable with e.g. hash_map
//
// Handle interaction with different C++ standard libraries, which
// expect these types to be in different namespaces.
#define FOLLY_FBSTRING_HASH1(T) \
template <> \
struct hash< ::folly::basic_fbstring<T> > { \
size_t operator()(const ::folly::fbstring& s) const { \
return ::folly::hash::fnv32_buf(s.data(), s.size()); \
} \
};

from folly.

 avatar commented on May 31, 2024

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

from folly.

chipturner avatar chipturner commented on May 31, 2024

Thank you for your patience. We're going to close out this issue. If you're still experiencing the problem described, please reopen the issue - thanks!

from folly.

chipturner avatar chipturner commented on May 31, 2024

Hello! This is a human. My previous comment on this issue was a robot running amok. I apologize that the issue was closed, and am re-opening it. Thanks for your help with our folly project and for your understanding about rogue robots trying to take over the world.

from folly.

christopherowen avatar christopherowen commented on May 31, 2024

Hello human. I haven't tried rebuilding in many months - I was left with the impression that folly would never run on OSx, and so I was unsurprised that the ticket was closed.

Perhaps interest will increase with the next release of OSx whose clang compiler may support thread_local, although I suspect more incompatibilities will just surface and we'll be in the same spot.

from folly.

sgolemon avatar sgolemon commented on May 31, 2024

The newest homebrew formula should work fine now.
Homebrew/legacy-homebrew@3ef948b

from folly.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.