/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2016-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <type_traits>
#include <utility>
+#include <folly/ConstexprMath.h>
+#include <folly/Portability.h>
+#include <folly/Range.h>
#include <folly/Utility.h>
#include <folly/portability/BitsFunctexcept.h>
#include <folly/portability/Constexpr.h>
-// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14
-// constexpr support is "good enough".
-#ifndef FOLLY_USE_CPP14_CONSTEXPR
-#if defined(__clang__)
-#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L
-#elif defined(__GNUC__)
-#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L
-#else
-#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC?
-#endif
-#endif
-
-#if FOLLY_USE_CPP14_CONSTEXPR
-#define FOLLY_CPP14_CONSTEXPR constexpr
-#else
-#define FOLLY_CPP14_CONSTEXPR inline
-#endif
-
namespace folly {
template <class Char, std::size_t N>
// Rather annoyingly, GCC's -Warray-bounds warning issues false positives for
// this code. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61971
-#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
}
};
-#if defined(__GNUC__) && !defined(__CLANG__) && __GNUC__ <= 4
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 4
#pragma GCC diagnostic pop
#endif
b = std::move(tmp);
}
-// FUTURE: use const_log2 to fold instantiations of BasicFixedString together.
-// All BasicFixedString<C, N> instantiations could share the implementation
-// of BasicFixedString<C, M>, where M is the next highest power of 2 after N.
-//
-// Also, because of alignment of the data_ and size_ members, N should never be
-// smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the null
-// terminator). OR, create a specialization for BasicFixedString<C, 0u> that
-// does not have a size_ member, since it is unnecessary.
-constexpr std::size_t const_log2(std::size_t N, std::size_t log2 = 0u) {
- return N / 2u == 0u ? log2 : const_log2(N / 2u, log2 + 1u);
-}
-
// For constexpr reverse iteration over a BasicFixedString
template <class T>
struct ReverseIterator {
} // namespace fixedstring
} // namespace detail
-// Defined in folly/Range.h
-template <class Iter>
-class Range;
-
-// Defined in folly/Hash.h
+// Defined in folly/hash/Hash.h
std::uint32_t hsieh_hash32_buf(const void* buf, std::size_t len);
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
friend class BasicFixedString;
friend struct detail::fixedstring::Helper;
+ // FUTURE: use constexpr_log2 to fold instantiations of BasicFixedString
+ // together. All BasicFixedString<C, N> instantiations could share the
+ // implementation of BasicFixedString<C, M>, where M is the next highest power
+ // of 2 after N.
+ //
+ // Also, because of alignment of the data_ and size_ members, N should never
+ // be smaller than `(alignof(std::size_t)/sizeof(C))-1` (-1 because of the
+ // null terminator). OR, create a specialization for BasicFixedString<C, 0u>
+ // that does not have a size_ member, since it is unnecessary.
Char data_[N + 1u]; // +1 for the null terminator
std::size_t size_; // Nbr of chars, not incl. null terminator. size_ <= N.
return *this;
}
- /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
- * Conversion to folly::Range
- * \return `Range<Iter>{begin(), end()}`
- */
- template <
- class Iter,
- class = typename std::enable_if<
- std::is_convertible<Char*, Iter>::value>::type>
- FOLLY_CPP14_CONSTEXPR /* implicit */ operator Range<Iter>() noexcept {
- return {begin(), end()};
- }
-
- /**
- * \overload
- */
- template <
- class Iter,
- class = typename std::enable_if<
- std::is_convertible<const Char*, Iter>::value>::type>
- constexpr /* implicit */ operator Range<Iter>() const noexcept {
- return {begin(), end()};
- }
-
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Conversion to folly::Range
* \return `Range<Char*>{begin(), end()}`
std::size_t count,
Char ch) noexcept(false) {
detail::fixedstring::checkOverflow(count, N - size_);
- for (std::size_t i = 0u; i < count; ++i)
+ for (std::size_t i = 0u; i < count; ++i) {
data_[size_ + i] = ch;
+ }
size_ += count;
data_[size_] = Char(0);
return *this;
detail::fixedstring::checkOverflow(pos, that.size_);
count = detail::fixedstring::checkOverflowOrNpos(count, that.size_ - pos);
detail::fixedstring::checkOverflow(count, N - size_);
- for (std::size_t i = 0u; i < count; ++i)
+ for (std::size_t i = 0u; i < count; ++i) {
data_[size_ + i] = that.data_[pos + i];
+ }
size_ += count;
data_[size_] = Char(0);
return *this;
const Char* that,
std::size_t count) noexcept(false) {
detail::fixedstring::checkOverflow(count, N - size_);
- for (std::size_t i = 0u; i < count; ++i)
+ for (std::size_t i = 0u; i < count; ++i) {
data_[size_ + i] = that[i];
+ }
size_ += count;
data_[size_] = Char(0);
return *this;
return compare(0u, size_, that, folly::constexpr_strlen(that));
}
+ /**
+ * \overload
+ */
+ constexpr int compare(Range<const Char*> that) const noexcept {
+ return compare(0u, size_, that.begin(), that.size());
+ }
+
/**
* Compare two strings for lexicographical ordering.
* \note Equivalent to
return compare(this_pos, this_count, that, folly::constexpr_strlen(that));
}
+ /**
+ * \overload
+ */
+ constexpr int compare(
+ std::size_t this_pos,
+ std::size_t this_count,
+ Range<const Char*> that) const noexcept(false) {
+ return compare(this_pos, this_count, that.begin(), that.size());
+ }
+
/**
* Compare two strings for lexicographical ordering.
*
that_count));
}
+ constexpr int compare(
+ std::size_t this_pos,
+ std::size_t this_count,
+ Range<const Char*> that,
+ std::size_t that_count) const noexcept(false) {
+ return compare(
+ this_pos,
+ this_count,
+ that.begin(),
+ detail::fixedstring::checkOverflow(that_count, that.size()));
+ }
+
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Return a substring from `pos` to the end of the string.
* \note Equivalent to `BasicFixedString{*this, pos}`
copy(Char* dest, std::size_t count, std::size_t pos) const noexcept(false) {
detail::fixedstring::checkOverflow(pos, size_);
for (std::size_t i = 0u; i < count; ++i) {
- if (i + pos == size_)
+ if (i + pos == size_) {
return size_;
+ }
dest[i] = data_[i + pos];
}
return count;
return b == a;
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator==(
+ Range<const Char*> a,
+ const BasicFixedString& b) noexcept {
+ return detail::fixedstring::equal_(a.begin(), a.size(), b.data_, b.size_);
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator==(
+ const BasicFixedString& a,
+ Range<const Char*> b) noexcept {
+ return b == a;
+ }
+
friend constexpr bool operator!=(
const Char* a,
const BasicFixedString& b) noexcept {
return !(b == a);
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator!=(
+ Range<const Char*> a,
+ const BasicFixedString& b) noexcept {
+ return !(a == b);
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator!=(
+ const BasicFixedString& a,
+ Range<const Char*> b) noexcept {
+ return !(a == b);
+ }
+
friend constexpr bool operator<(
const Char* a,
const BasicFixedString& b) noexcept {
a.data_, 0u, a.size_, b, 0u, folly::constexpr_strlen(b));
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator<(
+ Range<const Char*> a,
+ const BasicFixedString& b) noexcept {
+ return detail::fixedstring::Cmp::LT ==
+ detail::fixedstring::compare_(
+ a.begin(), 0u, a.size(), b.data_, 0u, b.size_);
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator<(
+ const BasicFixedString& a,
+ Range<const Char*> b) noexcept {
+ return detail::fixedstring::Cmp::LT ==
+ detail::fixedstring::compare_(
+ a.data_, 0u, a.size_, b.begin(), 0u, b.size());
+ }
+
friend constexpr bool operator>(
const Char* a,
const BasicFixedString& b) noexcept {
return b < a;
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator>(
+ Range<const Char*> a,
+ const BasicFixedString& b) noexcept {
+ return b < a;
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator>(
+ const BasicFixedString& a,
+ Range<const Char*> b) noexcept {
+ return b < a;
+ }
+
friend constexpr bool operator<=(
const Char* a,
const BasicFixedString& b) noexcept {
return !(b < a);
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator<=(
+ Range<const Char*> const& a,
+ const BasicFixedString& b) noexcept {
+ return !(b < a);
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator<=(
+ const BasicFixedString& a,
+ Range<const Char*> b) noexcept {
+ return !(b < a);
+ }
+
friend constexpr bool operator>=(
const Char* a,
const BasicFixedString& b) noexcept {
return !(a < b);
}
+ /**
+ * \overload
+ */
+ friend constexpr bool operator>=(
+ Range<const Char*> a,
+ const BasicFixedString& b) noexcept {
+ return !(a < b);
+ }
+
+ /**
+ * \overload
+ */
+ friend constexpr bool operator>=(
+ const BasicFixedString& a,
+ Range<const Char*> const& b) noexcept {
+ return !(a < b);
+ }
+
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Asymmetric concatenation
*/
}
};
+template <class C, std::size_t N>
+inline std::basic_ostream<C>& operator<<(
+ std::basic_ostream<C>& os,
+ const BasicFixedString<C, N>& string) {
+ using StreamSize = decltype(os.width());
+ os.write(string.begin(), static_cast<StreamSize>(string.size()));
+ return os;
+}
+
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
* Symmetric relational operators
*/
// "const std::size_t&" is so that folly::npos has the same address in every
// translation unit. This is to avoid potential violations of the ODR.
constexpr const std::size_t& npos = detail::fixedstring::FixedStringBase::npos;
-}
+} // namespace
#if defined(__GNUC__)
#pragma GCC diagnostic push
FOLLY_DEFINE_FIXED_STRING_UDL(128)
#undef FOLLY_DEFINE_FIXED_STRING_UDL
-}
-}
+} // namespace string_literals
+} // namespace literals
// TODO:
// // numeric conversions:
// constexpr FixedString</*...*/> to_fixed_string_ll() noexcept
// template <unsigned long long val>
// constexpr FixedString</*...*/> to_fixed_string_ull() noexcept;
-}
+} // namespace folly