Skip to content

Instantly share code, notes, and snippets.

@jimwwalker
Last active June 10, 2021 09:21
Show Gist options
  • Save jimwwalker/d62677965feb347f50c4c11bddc7ab6f to your computer and use it in GitHub Desktop.
Save jimwwalker/d62677965feb347f50c4c11bddc7ab6f to your computer and use it in GitHub Desktop.
Reproducer for gcc 10 template issue
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cmath>
#include <condition_variable>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <mutex>
#include <new>
#include <sstream>
#include <string_view>
#include <thread>
#include <type_traits>
#include <vector>
#include <arpa/inet.h>
#include <assert.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <poll.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
// # 1 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc"
// # 1 "/home/couchbase/couchbase//"
// # 1 "<built-in>"
// # 1 "<command-line>"
// # 1 "<command-line>" 2
// # 1 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc"
// # 12 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc"
// # 1 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.h" 1
// # 11 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.h"
// # 1 "/mnt/Code/couchbase/docker/kv_engine/include/memcached/vbucket.h" 1
// # 12 "/mnt/Code/couchbase/docker/kv_engine/include/memcached/vbucket.h"
// # 1 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 1
// # 17 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// # 1 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
// 1 # 14
// "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
// # 1 "platform/include/platform/dynamic.h" 1
// # 17 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
// 2
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Sockets.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Sockets.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Portability.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
static_assert(201703L >= 201402L, "__cplusplus >= 201402L");
static_assert(10 >= 5, "__GNUC__ >= 5");
// # 30 "tlm/deps/folly.exploded/include/folly/Portability.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/CPortability.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/CPortability.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Config.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Config.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/folly-config.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/folly-config.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/portability/Config.h" 2 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/CPortability.h" 2 3 4
// # 32 "tlm/deps/folly.exploded/include/folly/Portability.h" 2 3 4
namespace folly {
constexpr bool kHasUnalignedAccess = true;
}
// # 116 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
namespace folly {
constexpr bool kIsArchArm = 0 == 1;
constexpr bool kIsArchAmd64 = 1 == 1;
constexpr bool kIsArchAArch64 = 0 == 1;
constexpr bool kIsArchPPC64 = 0 == 1;
constexpr bool kIsArchS390X = 0 == 1;
} // namespace folly
namespace folly {
// # 135 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
constexpr bool kIsLibrarySanitizeAddress = false;
constexpr bool kIsSanitizeAddress = false;
constexpr bool kIsSanitizeThread = false;
constexpr bool kIsSanitize = false;
} // namespace folly
// # 305 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
namespace folly {
constexpr auto kIsDebug = true;
}
namespace folly {
constexpr auto kHasExceptions = true;
}
namespace folly {
// # 332 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
constexpr auto kIsLittleEndian = 1234 == 1234;
constexpr auto kIsBigEndian = !kIsLittleEndian;
} // namespace folly
// # 399 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
namespace folly {
constexpr bool const kHasRtti = 1;
}
// # 412 "tlm/deps/folly.exploded/include/folly/Portability.h" 3 4
namespace folly {
constexpr auto kIsObjC = false;
constexpr auto kIsMobile = false;
constexpr auto kIsLinux = true;
constexpr auto kIsWindows = false;
constexpr auto kIsGlibcxx = true;
constexpr auto kGlibcxxVer = 10;
constexpr auto kIsLibcpp = false;
constexpr auto kIsLibstdcpp = true;
constexpr auto kMscVer = 0;
constexpr auto kGnuc = 10;
constexpr auto kIsClang = false;
constexpr auto kMicrosoftAbiVer = 0;
constexpr auto kCpplibVer = 0;
} // namespace folly
// # 22 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/net/NetworkSocket.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/net/NetworkSocket.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/net/NetworkSocket.h" 2 3 4
// # 1
// "tlm/deps/folly.exploded/include/folly/net/detail/SocketFileDescriptorMap.h"
// 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/net/detail/SocketFileDescriptorMap.h"
// 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Windows.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Windows.h" 3 4
// # 20
// "tlm/deps/folly.exploded/include/folly/net/detail/SocketFileDescriptorMap.h"
// 2 3 4
// # 25
// "tlm/deps/folly.exploded/include/folly/net/detail/SocketFileDescriptorMap.h"
// 2 3 4
namespace folly {
namespace netops {
namespace detail {
struct SocketFileDescriptorMap {
static int close(int fd) noexcept {
return ::close(fd);
}
static int fdToSocket(int fd) noexcept {
return fd;
}
static int socketToFd(int sock) noexcept {
return sock;
}
};
} // namespace detail
} // namespace netops
} // namespace folly
// # 22 "tlm/deps/folly.exploded/include/folly/net/NetworkSocket.h" 2 3 4
namespace folly {
struct NetworkSocket {
using native_handle_type = int;
static constexpr native_handle_type invalid_handle_value = -1;
native_handle_type data;
constexpr NetworkSocket() : data(invalid_handle_value) {
}
constexpr explicit NetworkSocket(native_handle_type d) : data(d) {
}
template <typename T>
static NetworkSocket fromFd(T) = delete;
static NetworkSocket fromFd(int fd) {
return NetworkSocket(
netops::detail::SocketFileDescriptorMap::fdToSocket(fd));
}
int toFd() const {
return netops::detail::SocketFileDescriptorMap::socketToFd(data);
}
friend constexpr bool operator==(const NetworkSocket& a,
const NetworkSocket& b) noexcept {
return a.data == b.data;
}
friend constexpr bool operator!=(const NetworkSocket& a,
const NetworkSocket& b) noexcept {
return !(a == b);
}
};
template <class CharT, class Traits>
inline std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& os, const NetworkSocket& addr) {
os << "folly::NetworkSocket(" << addr.data << ")";
return os;
}
} // namespace folly
namespace std {
template <>
struct hash<folly::NetworkSocket> {
size_t operator()(const folly::NetworkSocket& s) const noexcept {
return std::hash<folly::NetworkSocket::native_handle_type>()(s.data);
}
};
} // namespace std
// # 23 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/IOVec.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/IOVec.h" 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/portability/IOVec.h" 2 3 4
// # 24 "tlm/deps/folly.exploded/include/folly/portability/IOVec.h" 2 3 4
// # 24 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/SysTypes.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/SysTypes.h" 3 4
// # 25 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Time.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Time.h" 3 4
// # 26 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 30 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 31 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 33 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 35 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 36 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 38 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 43 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 2 3 4
// # 156 "tlm/deps/folly.exploded/include/folly/net/NetOps.h" 3 4
namespace folly {
namespace netops {
struct PollDescriptor {
NetworkSocket fd;
int16_t events;
int16_t revents;
};
NetworkSocket accept(NetworkSocket s, sockaddr* addr, socklen_t* addrlen);
int bind(NetworkSocket s, const sockaddr* name, socklen_t namelen);
int close(NetworkSocket s);
int connect(NetworkSocket s, const sockaddr* name, socklen_t namelen);
int getpeername(NetworkSocket s, sockaddr* name, socklen_t* namelen);
int getsockname(NetworkSocket s, sockaddr* name, socklen_t* namelen);
int getsockopt(NetworkSocket s,
int level,
int optname,
void* optval,
socklen_t* optlen);
int inet_aton(const char* cp, in_addr* inp);
int listen(NetworkSocket s, int backlog);
int poll(PollDescriptor fds[], nfds_t nfds, int timeout);
ssize_t recv(NetworkSocket s, void* buf, size_t len, int flags);
ssize_t recvfrom(NetworkSocket s,
void* buf,
size_t len,
int flags,
sockaddr* from,
socklen_t* fromlen);
ssize_t recvmsg(NetworkSocket s, msghdr* message, int flags);
int recvmmsg(NetworkSocket s,
mmsghdr* msgvec,
unsigned int vlen,
unsigned int flags,
timespec* timeout);
ssize_t send(NetworkSocket s, const void* buf, size_t len, int flags);
ssize_t sendto(NetworkSocket s,
const void* buf,
size_t len,
int flags,
const sockaddr* to,
socklen_t tolen);
ssize_t sendmsg(NetworkSocket socket, const msghdr* message, int flags);
int sendmmsg(NetworkSocket socket,
mmsghdr* msgvec,
unsigned int vlen,
int flags);
int setsockopt(NetworkSocket s,
int level,
int optname,
const void* optval,
socklen_t optlen);
int shutdown(NetworkSocket s, int how);
NetworkSocket socket(int af, int type, int protocol);
int socketpair(int domain, int type, int protocol, NetworkSocket sv[2]);
int set_socket_non_blocking(NetworkSocket s);
int set_socket_close_on_exec(NetworkSocket s);
} // namespace netops
} // namespace folly
// # 20 "tlm/deps/folly.exploded/include/folly/portability/Sockets.h" 2 3 4
namespace folly {
namespace portability {
namespace sockets {
using ::accept;
using ::bind;
using ::connect;
using ::getpeername;
using ::getsockname;
using ::getsockopt;
using ::inet_ntop;
using ::listen;
using ::poll;
using ::recv;
using ::recvfrom;
using ::send;
using ::sendmsg;
using ::sendto;
using ::setsockopt;
using ::shutdown;
using ::socket;
// # 143 "tlm/deps/folly.exploded/include/folly/portability/Sockets.h" 3 4
} // namespace sockets
} // namespace portability
} // namespace folly
// # 19 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
// 2
// # 21 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
extern "C" {
// # 38 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
}
// # 1 "tlm/deps/folly.exploded/include/folly/Bits.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Bits.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 1 3 4
// # 54 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
// # 57 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 58 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 60 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 61 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/ConstexprMath.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/ConstexprMath.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/ConstexprMath.h" 2 3 4
namespace folly {
template <typename T>
constexpr T constexpr_max(T a) {
return a;
}
template <typename T, typename... Ts>
constexpr T constexpr_max(T a, T b, Ts... ts) {
return b < a ? constexpr_max(a, ts...) : constexpr_max(b, ts...);
}
template <typename T>
constexpr T constexpr_min(T a) {
return a;
}
template <typename T, typename... Ts>
constexpr T constexpr_min(T a, T b, Ts... ts) {
return b < a ? constexpr_min(b, ts...) : constexpr_min(a, ts...);
}
template <typename T, typename Less>
constexpr T const& constexpr_clamp(T const& v,
T const& lo,
T const& hi,
Less less) {
return less(v, lo) ? lo : less(hi, v) ? hi : v;
}
template <typename T>
constexpr T const& constexpr_clamp(T const& v, T const& lo, T const& hi) {
return constexpr_clamp(v, lo, hi, std::less<T>{});
}
namespace detail {
template <typename T, typename = void>
struct constexpr_abs_helper {};
template <typename T>
struct constexpr_abs_helper<
T,
typename std::enable_if<std::is_floating_point<T>::value>::type> {
static constexpr T go(T t) {
return t < static_cast<T>(0) ? -t : t;
}
};
template <typename T>
struct constexpr_abs_helper<
T,
typename std::enable_if<std::is_integral<T>::value &&
!std::is_same<T, bool>::value &&
std::is_unsigned<T>::value>::type> {
static constexpr T go(T t) {
return t;
}
};
template <typename T>
struct constexpr_abs_helper<
T,
typename std::enable_if<std::is_integral<T>::value &&
!std::is_same<T, bool>::value &&
std::is_signed<T>::value>::type> {
static constexpr typename std::make_unsigned<T>::type go(T t) {
return typename std::make_unsigned<T>::type(t < static_cast<T>(0) ? -t
: t);
}
};
} // namespace detail
template <typename T>
constexpr auto constexpr_abs(T t)
-> decltype(detail::constexpr_abs_helper<T>::go(t)) {
return detail::constexpr_abs_helper<T>::go(t);
}
namespace detail {
template <typename T>
constexpr T constexpr_log2_(T a, T e) {
return e == T(1) ? a : constexpr_log2_(a + T(1), e / T(2));
}
template <typename T>
constexpr T constexpr_log2_ceil_(T l2, T t) {
return l2 + T(T(1) << l2 < t ? 1 : 0);
}
template <typename T>
constexpr T constexpr_square_(T t) {
return t * t;
}
} // namespace detail
template <typename T>
constexpr T constexpr_log2(T t) {
return detail::constexpr_log2_(T(0), t);
}
template <typename T>
constexpr T constexpr_log2_ceil(T t) {
return detail::constexpr_log2_ceil_(constexpr_log2(t), t);
}
template <typename T>
constexpr T constexpr_ceil(T t, T round) {
return round == T(0)
? t
: ((t + (t < T(0) ? T(0) : round - T(1))) / round) * round;
}
template <typename T>
constexpr T constexpr_pow(T base, std::size_t exp) {
return exp == 0 ? T(1)
: exp == 1 ? base
: detail::constexpr_square_(
constexpr_pow(base, exp / 2)) *
(exp % 2 ? base : T(1));
}
template <typename T>
constexpr std::size_t constexpr_find_last_set(T const t) {
using U = std::make_unsigned_t<T>;
return t == T(0) ? 0 : 1 + constexpr_log2(static_cast<U>(t));
}
namespace detail {
template <typename U>
constexpr std::size_t constexpr_find_first_set_(std::size_t s,
std::size_t a,
U const u) {
return s == 0 ? a
: constexpr_find_first_set_(
s / 2,
a + s * bool((u >> a) % (U(1) << s) == U(0)),
u);
}
} // namespace detail
template <typename T>
constexpr std::size_t constexpr_find_first_set(T t) {
using U = std::make_unsigned_t<T>;
using size = std::integral_constant<std::size_t, sizeof(T) * 4>;
return t == T(0) ? 0
: 1 + detail::constexpr_find_first_set_(
size{}, 0, static_cast<U>(t));
}
template <typename T>
constexpr T constexpr_add_overflow_clamped(T a, T b) {
using L = std::numeric_limits<T>;
using M = std::intmax_t;
static_assert(!std::is_integral<T>::value || sizeof(T) <= sizeof(M),
"Integral type too large!");
return
!std::is_integral<T>::value
? a + b
:
sizeof(T) < sizeof(M)
? T(constexpr_clamp(
M(a) + M(b), M(L::min()), M(L::max())))
:
!(a < 0) ? a + constexpr_min(b, T(L::max() - a)) :
!(b < 0) ? a + b :
a + constexpr_max(
b, T(L::min() - a));
}
template <typename T>
constexpr T constexpr_sub_overflow_clamped(T a, T b) {
using L = std::numeric_limits<T>;
using M = std::intmax_t;
static_assert(!std::is_integral<T>::value || sizeof(T) <= sizeof(M),
"Integral type too large!");
return
!std::is_integral<T>::value
? a - b
:
std::is_unsigned<T>::value
? (a < b ? 0 : a - b)
:
sizeof(T) < sizeof(M)
? T(constexpr_clamp(M(a) - M(b),
M(L::min()),
M(L::max())))
:
(a < 0) == (b < 0)
? a - b
:
L::min() < b
? constexpr_add_overflow_clamped(
a, T(-b))
:
a < 0 ? a - b :
L::max();
}
// # 263 "tlm/deps/folly.exploded/include/folly/ConstexprMath.h" 3 4
template <typename Dst, typename Src>
constexpr typename std::enable_if<std::is_integral<Src>::value, Dst>::type
constexpr_clamp_cast(Src src) {
static_assert(
std::is_integral<Dst>::value && sizeof(Dst) <= sizeof(int64_t),
"constexpr_clamp_cast can only cast into integral type (up to "
"64bit)");
using L = std::numeric_limits<Dst>;
return
std::is_signed<Src>::value == std::is_signed<Dst>::value
? (
sizeof(Src) <= sizeof(Dst)
? Dst(src)
:
Dst(constexpr_clamp(src,
Src(L::min()),
Src(L::max()))))
: std::is_signed<Src>::value && std::is_unsigned<Dst>::value
? (
src < 0 ? Dst(0) :
sizeof(Src) <= sizeof(Dst)
? Dst(src)
:
Dst(constexpr_min(
src,
Src(L::max()))))
: (
sizeof(Src) < sizeof(Dst)
? Dst(src)
:
Dst(constexpr_min(
src, Src(L::max()))));
}
namespace detail {
constexpr double kClampCastLowerBoundDoubleToInt64F = -9223372036854774784.0;
constexpr double kClampCastUpperBoundDoubleToInt64F = 9223372036854774784.0;
constexpr double kClampCastUpperBoundDoubleToUInt64F = 18446744073709549568.0;
constexpr float kClampCastLowerBoundFloatToInt32F = -2147483520.0f;
constexpr float kClampCastUpperBoundFloatToInt32F = 2147483520.0f;
constexpr float kClampCastUpperBoundFloatToUInt32F = 4294967040.0f;
template <typename D, typename S>
constexpr D constexpr_clamp_cast_helper(S src, S sl, S su, D dl, D du) {
return src < sl ? dl : (src > su ? du : D(src));
}
} // namespace detail
template <typename Dst, typename Src>
constexpr typename std::enable_if<std::is_floating_point<Src>::value, Dst>::type
constexpr_clamp_cast(Src src) {
static_assert(
std::is_integral<Dst>::value && sizeof(Dst) <= sizeof(int64_t),
"constexpr_clamp_cast can only cast into integral type (up to "
"64bit)");
using L = std::numeric_limits<Dst>;
return
(src != src)
? Dst(0)
:
sizeof(Src) > sizeof(Dst)
? detail::constexpr_clamp_cast_helper(src,
Src(L::min()),
Src(L::max()),
L::min(),
L::max())
:
sizeof(Src) < sizeof(Dst)
? (src >= 0.0
? constexpr_clamp_cast<Dst>(
constexpr_clamp_cast<
std::uint64_t>(
double(src)))
: constexpr_clamp_cast<Dst>(
constexpr_clamp_cast<
std::int64_t>(
double(src))))
:
std::is_same<Src, double>::value &&
std::is_same<Dst,
int64_t>::value
? detail::constexpr_clamp_cast_helper(
double(src),
detail::kClampCastLowerBoundDoubleToInt64F,
detail::kClampCastUpperBoundDoubleToInt64F,
L::min(),
L::max())
: std::is_same<Src,
double>::value &&
std::is_same<
Dst,
uint64_t>::
value
? detail::constexpr_clamp_cast_helper(
double(src),
0.0,
detail::kClampCastUpperBoundDoubleToUInt64F,
L::min(),
L::max())
: std::is_same<
Src,
float>::value &&
std::is_same<
Dst,
int32_t>::
value
? detail::constexpr_clamp_cast_helper(
float(src),
detail::kClampCastLowerBoundFloatToInt32F,
detail::kClampCastUpperBoundFloatToInt32F,
L::min(),
L::max())
: detail::constexpr_clamp_cast_helper(
float(src),
0.0f,
detail::kClampCastUpperBoundFloatToUInt32F,
L::min(),
L::max());
}
} // namespace folly
// # 64 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Traits.h" 1 3 4
// # 19 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
// # 24 "tlm/deps/folly.exploded/include/folly/Traits.h" 2 3 4
// # 125 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
namespace folly {
template <typename...>
struct tag_t {};
template <typename... T>
inline constexpr tag_t<T...> tag;
using std::bool_constant;
// # 149 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <std::size_t I>
using index_constant = std::integral_constant<std::size_t, I>;
namespace detail {
// # 162 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <template <typename...> class, typename>
struct is_instantiation_of : std::false_type {};
template <template <typename...> class C, typename... T>
struct is_instantiation_of<C, C<T...>> : std::true_type {};
template <template <typename...> class C, typename T>
constexpr bool is_instantiation_of_v = is_instantiation_of<C, T>::value;
} // namespace detail
namespace detail {
template <bool, typename T>
struct is_constexpr_default_constructible_;
template <typename T>
struct is_constexpr_default_constructible_<false, T> {
using type = std::false_type;
};
template <typename T>
struct is_constexpr_default_constructible_<true, T> {
static constexpr int take(T) {
return 0;
}
template <int = take(T{})>
static std::true_type sfinae(int);
static std::false_type sfinae(...);
using type = decltype(sfinae(0));
};
} // namespace detail
// # 201 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename T>
struct is_constexpr_default_constructible
: detail::is_constexpr_default_constructible_<
std::is_default_constructible<T>::value,
T>::type {};
template <typename T>
inline constexpr bool is_constexpr_default_constructible_v =
is_constexpr_default_constructible<T>::value;
// # 228 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename T>
using _t = typename T::type;
template <typename T>
struct remove_cvref {
using type = typename std::remove_cv<
typename std::remove_reference<T>::type>::type;
};
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
namespace detail {
template <typename Src>
struct like_ {
template <typename Dst>
using apply = Dst;
};
template <typename Src>
struct like_<Src const> {
template <typename Dst>
using apply = Dst const;
};
template <typename Src>
struct like_<Src volatile> {
template <typename Dst>
using apply = Dst volatile;
};
template <typename Src>
struct like_<Src const volatile> {
template <typename Dst>
using apply = Dst const volatile;
};
template <typename Src>
struct like_<Src&> {
template <typename Dst>
using apply = typename like_<Src>::template apply<Dst>&;
};
template <typename Src>
struct like_<Src&&> {
template <typename Dst>
using apply = typename like_<Src>::template apply<Dst>&&;
};
} // namespace detail
template <typename Src, typename Dst>
using like_t = typename detail::like_<Src>::template apply<remove_cvref_t<Dst>>;
template <typename Src, typename Dst>
struct like {
using type = like_t<Src, Dst>;
};
// # 350 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
namespace traits_detail {
template <class T, class...>
struct type_t_ {
using type = T;
};
} // namespace traits_detail
template <class T, class... Ts>
using type_t = typename traits_detail::type_t_<T, Ts...>::type;
template <class... Ts>
using void_t = type_t<void, Ts...>;
template <typename T>
using aligned_storage_for_t =
typename std::aligned_storage<sizeof(T), alignof(T)>::type;
template <class T>
using is_trivially_copyable = std::is_trivially_copyable<T>;
template <class T>
inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
// # 421 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
namespace traits_detail {
// # 433 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename TTheClass_>
struct has_IsRelocatable__folly_traits_impl__ {
template <typename UTheClass_>
static constexpr bool test(typename UTheClass_::IsRelocatable*) {
return true;
}
template <typename>
static constexpr bool test(...) {
return false;
}
};
template <typename TTheClass_>
using has_IsRelocatable = typename std::conditional<
has_IsRelocatable__folly_traits_impl__<TTheClass_>::template test<
TTheClass_>(nullptr),
std::true_type,
std::false_type>::type;
template <class T>
struct IsRelocatable_is_true
: std::is_same<typename T::IsRelocatable, std::true_type> {};
template <class T>
struct has_true_IsRelocatable : std::conditional<has_IsRelocatable<T>::value,
IsRelocatable_is_true<T>,
std::false_type>::type {};
template <typename TTheClass_>
struct has_IsZeroInitializable__folly_traits_impl__ {
template <typename UTheClass_>
static constexpr bool test(typename UTheClass_::IsZeroInitializable*) {
return true;
}
template <typename>
static constexpr bool test(...) {
return false;
}
};
template <typename TTheClass_>
using has_IsZeroInitializable = typename std::conditional<
has_IsZeroInitializable__folly_traits_impl__<TTheClass_>::template test<
TTheClass_>(nullptr),
std::true_type,
std::false_type>::type;
template <class T>
struct IsZeroInitializable_is_true
: std::is_same<typename T::IsZeroInitializable, std::true_type> {};
template <class T>
struct has_true_IsZeroInitializable
: std::conditional<has_IsZeroInitializable<T>::value,
IsZeroInitializable_is_true<T>,
std::false_type>::type {};
} // namespace traits_detail
struct Ignore {
Ignore() = default;
template <class T>
constexpr Ignore(const T&) {
}
template <class T>
const Ignore& operator=(T const&) const {
return *this;
}
};
template <class...>
using Ignored = Ignore;
namespace traits_detail_IsEqualityComparable {
Ignore operator==(Ignore, Ignore);
template <class T, class U = T>
struct IsEqualityComparable
: std::is_convertible<decltype(std::declval<T>() == std::declval<U>()),
bool> {};
} // namespace traits_detail_IsEqualityComparable
using traits_detail_IsEqualityComparable::IsEqualityComparable;
namespace traits_detail_IsLessThanComparable {
Ignore operator<(Ignore, Ignore);
template <class T, class U = T>
struct IsLessThanComparable
: std::is_convertible<decltype(std::declval<T>() < std::declval<U>()),
bool> {};
} // namespace traits_detail_IsLessThanComparable
using traits_detail_IsLessThanComparable::IsLessThanComparable;
namespace traits_detail_IsNothrowSwappable {
template <typename T>
using IsNothrowSwappable = std::is_nothrow_swappable<T>;
// # 500 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
} // namespace traits_detail_IsNothrowSwappable
using traits_detail_IsNothrowSwappable::IsNothrowSwappable;
template <class T>
struct IsRelocatable
: std::conditional<traits_detail::has_IsRelocatable<T>::value,
traits_detail::has_true_IsRelocatable<T>,
is_trivially_copyable<T>>::type {};
template <class T>
struct IsZeroInitializable
: std::conditional<traits_detail::has_IsZeroInitializable<T>::value,
traits_detail::has_true_IsZeroInitializable<T>,
bool_constant<!std::is_class<T>::value>>::type {};
namespace detail {
template <bool>
struct conditional_;
template <>
struct conditional_<false> {
template <typename, typename T>
using apply = T;
};
template <>
struct conditional_<true> {
template <typename T, typename>
using apply = T;
};
} // namespace detail
// # 542 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <bool V, typename T, typename F>
using conditional_t = typename detail::conditional_<V>::template apply<T, F>;
template <typename...>
struct Conjunction : std::true_type {};
template <typename T>
struct Conjunction<T> : T {};
template <typename T, typename... TList>
struct Conjunction<T, TList...>
: std::conditional<T::value, Conjunction<TList...>, T>::type {};
template <typename...>
struct Disjunction : std::false_type {};
template <typename T>
struct Disjunction<T> : T {};
template <typename T, typename... TList>
struct Disjunction<T, TList...>
: std::conditional<T::value, T, Disjunction<TList...>>::type {};
template <typename T>
struct Negation : bool_constant<!T::value> {};
template <bool... Bs>
struct Bools {
using valid_type = bool;
static constexpr std::size_t size() {
return sizeof...(Bs);
}
};
template <class... Ts>
struct StrictConjunction
: std::is_same<Bools<Ts::value...>, Bools<(Ts::value || true)...>> {};
template <class... Ts>
struct StrictDisjunction
: Negation<std::is_same<Bools<Ts::value...>,
Bools<(Ts::value && false)...>>> {};
namespace detail {
template <typename, typename>
struct is_transparent_ : std::false_type {};
template <typename T>
struct is_transparent_<void_t<typename T::is_transparent>, T> : std::true_type {
};
} // namespace detail
template <typename T>
struct is_transparent : detail::is_transparent_<void, T> {};
} // namespace folly
// # 670 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
namespace folly {
template <class T, class U>
struct IsRelocatable<std::pair<T, U>>
: bool_constant<IsRelocatable<T>::value && IsRelocatable<U>::value> {};
template <typename T, typename... Ts>
using IsOneOf = StrictDisjunction<std::is_same<T, Ts>...>;
// # 692 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename T>
constexpr bool is_negative(T x) {
return std::is_signed<T>::value && x < T(0);
}
template <typename T>
constexpr bool is_non_positive(T x) {
return !x || folly::is_negative(x);
}
template <typename T>
constexpr bool is_positive(T x) {
return !is_non_positive(x);
}
template <typename T>
constexpr bool is_non_negative(T x) {
return !x || is_positive(x);
}
namespace detail {
// # 721 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
#pragma GCC diagnostic push
// # 721 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
// # 722 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
#pragma GCC diagnostic ignored "-Wsign-compare"
// # 722 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
// # 723 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
#pragma GCC diagnostic ignored "-Wbool-compare"
// # 723 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename RHS, RHS rhs, typename LHS>
bool less_than_impl(LHS const lhs) {
return
(!std::is_signed<RHS>::value && is_negative(lhs))
? true
: (!std::is_signed<LHS>::value && is_negative(rhs))
? false
: rhs > std::numeric_limits<LHS>::max()
? true
: rhs <= std::numeric_limits<LHS>::min()
? false
: lhs < rhs;
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than_impl(LHS const lhs) {
return
(!std::is_signed<RHS>::value && is_negative(lhs))
? false
: (!std::is_signed<LHS>::value && is_negative(rhs))
? true
: rhs > std::numeric_limits<LHS>::max()
? false
: rhs < std::numeric_limits<LHS>::min()
? true
: lhs > rhs;
}
// # 754 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
#pragma GCC diagnostic pop
// # 754 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
} // namespace detail
template <typename RHS, RHS rhs, typename LHS>
bool less_than(LHS const lhs) {
return detail::
less_than_impl<RHS, rhs, typename std::remove_reference<LHS>::type>(
lhs);
}
template <typename RHS, RHS rhs, typename LHS>
bool greater_than(LHS const lhs) {
return detail::greater_than_impl<RHS,
rhs,
typename std::remove_reference<LHS>::type>(
lhs);
}
} // namespace folly
namespace folly {
template <class T1, class T2>
struct IsRelocatable<std::unique_ptr<T1, T2>> : std::true_type {};
} // namespace folly
namespace folly {
template <class T1>
struct IsRelocatable<std::shared_ptr<T1>> : std::true_type {};
} // namespace folly
// # 820 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
namespace folly {
// # 833 "tlm/deps/folly.exploded/include/folly/Traits.h" 3 4
template <typename Container>
const Container& order_preserving_reinsertion_view(const Container& container) {
return container;
}
} // namespace folly
// # 66 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Utility.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
// # 28 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
namespace folly {
// # 72 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
template <typename T>
constexpr typename std::decay<T>::type copy(T&& value) noexcept(
noexcept(typename std::decay<T>::type(std::forward<T>(value)))) {
return std::forward<T>(value);
}
// # 92 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
using std::as_const;
// # 107 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
template <typename Src, typename Dst>
constexpr like_t<Src, Dst>&& forward_like(Dst&& dst) noexcept {
return static_cast<like_t<Src, Dst>&&>(std::forward<Dst>(dst));
}
// # 122 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
struct in_place_tag {};
template <class>
struct in_place_type_tag {};
template <std::size_t>
struct in_place_index_tag {};
using in_place_t = in_place_tag (&)(in_place_tag);
template <class T>
using in_place_type_t = in_place_type_tag<T> (&)(in_place_type_tag<T>);
template <std::size_t I>
using in_place_index_t = in_place_index_tag<I> (&)(in_place_index_tag<I>);
inline in_place_tag in_place(in_place_tag = {}) {
return {};
}
template <class T>
inline in_place_type_tag<T> in_place_type(in_place_type_tag<T> = {}) {
return {};
}
template <std::size_t I>
inline in_place_index_tag<I> in_place_index(in_place_index_tag<I> = {}) {
return {};
}
// # 188 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
struct initlist_construct_t {};
constexpr initlist_construct_t initlist_construct{};
// # 212 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
struct sorted_unique_t {};
constexpr sorted_unique_t sorted_unique;
// # 235 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
struct sorted_equivalent_t {};
constexpr sorted_equivalent_t sorted_equivalent;
template <typename T>
struct transparent : T {
using is_transparent = void;
using T::T;
};
// # 263 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
struct identity_fn {
template <class T>
constexpr T&& operator()(T&& x) const noexcept {
return static_cast<T&&>(x);
}
};
using Identity = identity_fn;
inline constexpr identity_fn identity;
namespace moveonly_ {
class MoveOnly {
protected:
constexpr MoveOnly() = default;
~MoveOnly() = default;
MoveOnly(MoveOnly&&) = default;
MoveOnly& operator=(MoveOnly&&) = default;
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator=(const MoveOnly&) = delete;
};
} // namespace moveonly_
using MoveOnly = moveonly_::MoveOnly;
template <typename T>
constexpr auto to_signed(T const& t) -> typename std::make_signed<T>::type {
using S = typename std::make_signed<T>::type;
constexpr auto m = static_cast<T>(std::numeric_limits<S>::max());
return m < t ? -static_cast<S>(~t) + S{-1} : static_cast<S>(t);
}
template <typename T>
constexpr auto to_unsigned(T const& t) -> typename std::make_unsigned<T>::type {
using U = typename std::make_unsigned<T>::type;
return static_cast<U>(t);
}
template <typename Src>
class to_narrow_convertible {
public:
static_assert(std::is_integral<Src>::value, "not an integer");
explicit constexpr to_narrow_convertible(Src const& value) noexcept
: value_(value) {
}
explicit to_narrow_convertible(to_narrow_convertible const&) = default;
explicit to_narrow_convertible(to_narrow_convertible&&) = default;
to_narrow_convertible& operator=(to_narrow_convertible const&) = default;
to_narrow_convertible& operator=(to_narrow_convertible&&) = default;
template <typename Dst,
std::enable_if_t<std::is_integral<Dst>::value &&
std::is_signed<Dst>::value ==
std::is_signed<Src>::value,
int> = 0>
constexpr operator Dst() const noexcept {
// # 334 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
#pragma GCC diagnostic push
// # 334 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
// # 337 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
#pragma GCC diagnostic ignored "-Wconversion"
// # 337 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
return value_;
// # 339 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
#pragma GCC diagnostic pop
// # 339 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
}
private:
Src value_;
};
// # 359 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
template <typename Src>
constexpr auto to_narrow(Src const& src) -> to_narrow_convertible<Src> {
return to_narrow_convertible<Src>{src};
}
template <class E>
constexpr std::underlying_type_t<E> to_underlying(E e) noexcept {
static_assert(std::is_enum<E>::value, "not an enum type");
return static_cast<std::underlying_type_t<E>>(e);
}
// # 403 "tlm/deps/folly.exploded/include/folly/Utility.h" 3 4
} // namespace folly
// # 67 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Assume.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/Assume.h" 3 4
namespace folly {
// # 54 "tlm/deps/folly.exploded/include/folly/lang/Assume.h" 3 4
inline __attribute__((__always_inline__)) void assume(bool cond);
// # 65 "tlm/deps/folly.exploded/include/folly/lang/Assume.h" 3 4
[[noreturn]] inline __attribute__((__always_inline__)) void
assume_unreachable();
} // namespace folly
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Assume-inl.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/Assume-inl.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/lang/Assume-inl.h" 2 3 4
namespace folly {
namespace detail {
extern void assume_check(bool cond);
}
inline __attribute__((__always_inline__)) void assume(bool cond) {
if (kIsDebug) {
detail::assume_check(cond);
} else {
if (!cond) {
__builtin_unreachable();
}
}
}
[[noreturn]] inline __attribute__((__always_inline__)) void
assume_unreachable() {
assume(false);
__builtin_unreachable();
}
} // namespace folly
// # 70 "tlm/deps/folly.exploded/include/folly/lang/Assume.h" 2 3 4
// # 68 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Builtins.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Builtins.h" 3 4
// # 69 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
// # 72 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 2 3 4
namespace folly {
// # 83 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
template <typename To,
typename From,
std::enable_if_t<sizeof(From) == sizeof(To) &&
is_trivially_copyable<To>::value &&
is_trivially_copyable<From>::value,
int> = 0>
To bit_cast(const From& src) noexcept {
aligned_storage_for_t<To> storage;
std::memcpy(&storage, &src, sizeof(From));
return reinterpret_cast<To&>(storage);
}
namespace detail {
template <typename Dst, typename Src>
constexpr std::make_signed_t<Dst> bits_to_signed(Src const s) {
static_assert(std::is_signed<Dst>::value, "unsigned type");
return to_signed(static_cast<std::make_unsigned_t<Dst>>(to_unsigned(s)));
}
template <typename Dst, typename Src>
constexpr std::make_unsigned_t<Dst> bits_to_unsigned(Src const s) {
static_assert(std::is_unsigned<Dst>::value, "signed type");
return static_cast<Dst>(to_unsigned(s));
}
} // namespace detail
template <typename T>
inline constexpr unsigned int findFirstSet(T const v) {
using S0 = int;
using S1 = long int;
using S2 = long long int;
using detail::bits_to_signed;
static_assert(sizeof(T) <= sizeof(S2), "over-sized type");
static_assert(std::is_integral<T>::value, "non-integral type");
static_assert(!std::is_same<T, bool>::value, "bool type");
return static_cast<unsigned int>(
sizeof(T) <= sizeof(S0)
? __builtin_ffs(bits_to_signed<S0>(v))
: sizeof(T) <= sizeof(S1)
? __builtin_ffsl(bits_to_signed<S1>(v))
: sizeof(T) <= sizeof(S2)
? __builtin_ffsll(bits_to_signed<S2>(v))
: 0);
}
template <typename T>
inline constexpr unsigned int findLastSet(T const v) {
using U0 = unsigned int;
using U1 = unsigned long int;
using U2 = unsigned long long int;
using detail::bits_to_unsigned;
static_assert(sizeof(T) <= sizeof(U2), "over-sized type");
static_assert(std::is_integral<T>::value, "non-integral type");
static_assert(!std::is_same<T, bool>::value, "bool type");
using size = index_constant<constexpr_max(sizeof(T), sizeof(U0))>;
return v ? 1u + static_cast<unsigned int>(
(8u * size{} - 1u) ^
(sizeof(T) <= sizeof(U0)
? __builtin_clz(bits_to_unsigned<U0>(v))
: sizeof(T) <= sizeof(U1)
? __builtin_clzl(
bits_to_unsigned<U1>(
v))
: sizeof(T) <= sizeof(U2)
? __builtin_clzll(
bits_to_unsigned<
U2>(
v))
: 0))
: 0u;
}
template <typename T>
inline constexpr T extractFirstSet(T const v) {
static_assert(std::is_integral<T>::value, "non-integral type");
static_assert(std::is_unsigned<T>::value, "signed type");
static_assert(!std::is_same<T, bool>::value, "bool type");
return v & -v;
}
template <typename T>
inline constexpr unsigned int popcount(T const v) {
using U0 = unsigned int;
using U1 = unsigned long int;
using U2 = unsigned long long int;
using detail::bits_to_unsigned;
static_assert(sizeof(T) <= sizeof(U2), "over-sized type");
static_assert(std::is_integral<T>::value, "non-integral type");
static_assert(!std::is_same<T, bool>::value, "bool type");
return static_cast<unsigned int>(
sizeof(T) <= sizeof(U0)
? __builtin_popcount(bits_to_unsigned<U0>(v))
: sizeof(T) <= sizeof(U1)
? __builtin_popcountl(bits_to_unsigned<U1>(v))
: sizeof(T) <= sizeof(U2)
? __builtin_popcountll(
bits_to_unsigned<U2>(v))
: 0);
}
template <class T>
inline constexpr T nextPowTwo(T const v) {
static_assert(std::is_unsigned<T>::value, "signed type");
return v ? (T(1) << findLastSet(v - 1)) : T(1);
}
template <class T>
inline constexpr T prevPowTwo(T const v) {
static_assert(std::is_unsigned<T>::value, "signed type");
return v ? (T(1) << (findLastSet(v) - 1)) : T(0);
}
template <class T>
inline constexpr bool isPowTwo(T const v) {
static_assert(std::is_integral<T>::value, "non-integral type");
static_assert(std::is_unsigned<T>::value, "signed type");
static_assert(!std::is_same<T, bool>::value, "bool type");
return (v != 0) && !(v & (v - 1));
}
template <class T>
inline constexpr T strictNextPowTwo(T const v) {
static_assert(std::is_unsigned<T>::value, "signed type");
return nextPowTwo(T(v + 1));
}
template <class T>
inline constexpr T strictPrevPowTwo(T const v) {
static_assert(std::is_unsigned<T>::value, "signed type");
return v > 1 ? prevPowTwo(T(v - 1)) : T(0);
}
namespace detail {
template <size_t Size>
struct uint_types_by_size;
// # 243 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
static inline uint8_t byteswap_gen(uint8_t v) {
return uint8_t(v);
}
template <>
struct uint_types_by_size<8 / 8> {
using type = uint8_t;
};
static inline uint64_t byteswap_gen(uint64_t v) {
return __builtin_bswap64(v);
}
template <>
struct uint_types_by_size<64 / 8> {
using type = uint64_t;
};
static inline uint32_t byteswap_gen(uint32_t v) {
return __builtin_bswap32(v);
}
template <>
struct uint_types_by_size<32 / 8> {
using type = uint32_t;
};
static inline uint16_t byteswap_gen(uint16_t v) {
return __builtin_bswap16(v);
}
template <>
struct uint_types_by_size<16 / 8> {
using type = uint16_t;
};
template <class T>
struct EndianInt {
static_assert((std::is_integral<T>::value &&
!std::is_same<T, bool>::value) ||
std::is_floating_point<T>::value,
"template type parameter must be non-bool integral or "
"floating point");
static T swap(T x) {
constexpr auto s = sizeof(T);
using B = typename uint_types_by_size<s>::type;
return bit_cast<T>(byteswap_gen(bit_cast<B>(x)));
}
static T big(T x) {
return kIsLittleEndian ? EndianInt::swap(x) : x;
}
static T little(T x) {
return kIsBigEndian ? EndianInt::swap(x) : x;
}
};
} // namespace detail
// # 299 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
class Endian {
public:
enum class Order : uint8_t {
LITTLE,
BIG,
};
static constexpr Order order = kIsLittleEndian ? Order::LITTLE : Order::BIG;
template <class T>
static T swap(T x) {
return folly::detail::EndianInt<T>::swap(x);
}
template <class T>
static T big(T x) {
return folly::detail::EndianInt<T>::big(x);
}
template <class T>
static T little(T x) {
return folly::detail::EndianInt<T>::little(x);
}
static uint64_t swap64(uint64_t x) {
return swap<uint64_t>(x);
}
static uint64_t big64(uint64_t x) {
return big<uint64_t>(x);
}
static uint64_t little64(uint64_t x) {
return little<uint64_t>(x);
}
static int64_t swap64(int64_t x) {
return swap<int64_t>(x);
}
static int64_t big64(int64_t x) {
return big<int64_t>(x);
}
static int64_t little64(int64_t x) {
return little<int64_t>(x);
}
static uint32_t swap32(uint32_t x) {
return swap<uint32_t>(x);
}
static uint32_t big32(uint32_t x) {
return big<uint32_t>(x);
}
static uint32_t little32(uint32_t x) {
return little<uint32_t>(x);
}
static int32_t swap32(int32_t x) {
return swap<int32_t>(x);
}
static int32_t big32(int32_t x) {
return big<int32_t>(x);
}
static int32_t little32(int32_t x) {
return little<int32_t>(x);
}
static uint16_t swap16(uint16_t x) {
return swap<uint16_t>(x);
}
static uint16_t big16(uint16_t x) {
return big<uint16_t>(x);
}
static uint16_t little16(uint16_t x) {
return little<uint16_t>(x);
}
static int16_t swap16(int16_t x) {
return swap<int16_t>(x);
}
static int16_t big16(int16_t x) {
return big<int16_t>(x);
}
static int16_t little16(int16_t x) {
return little<int16_t>(x);
}
static uint8_t swap8(uint8_t x) {
return swap<uint8_t>(x);
}
static uint8_t big8(uint8_t x) {
return big<uint8_t>(x);
}
static uint8_t little8(uint8_t x) {
return little<uint8_t>(x);
}
static int8_t swap8(int8_t x) {
return swap<int8_t>(x);
}
static int8_t big8(int8_t x) {
return big<int8_t>(x);
}
static int8_t little8(int8_t x) {
return little<int8_t>(x);
}
};
template <class T, class Enable = void>
struct Unaligned;
// # 339 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
#pragma GCC diagnostic push
// # 339 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
template <class T>
struct Unaligned<T, typename std::enable_if<std::is_pod<T>::value>::type> {
Unaligned() = default;
Unaligned(T v) : value(v) {
}
T value;
} __attribute__((__packed__));
// # 349 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
#pragma GCC diagnostic pop
// # 349 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
template <class T>
inline T loadUnaligned(const void* p) {
static_assert(sizeof(Unaligned<T>) == sizeof(T), "Invalid unaligned size");
static_assert(alignof(Unaligned<T>) == 1, "Invalid alignment");
if (kHasUnalignedAccess) {
return static_cast<const Unaligned<T>*>(p)->value;
} else {
T value;
memcpy(&value, p, sizeof(T));
return value;
}
}
// # 374 "tlm/deps/folly.exploded/include/folly/lang/Bits.h" 3 4
template <class T>
inline T partialLoadUnaligned(const void* p, size_t l) {
static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value &&
sizeof(T) <= 8,
"Invalid type");
assume(l < sizeof(T));
auto cp = static_cast<const char*>(p);
T value = 0;
if (!kHasUnalignedAccess || !kIsLittleEndian) {
memcpy(&value, cp, l);
return value;
}
auto avail = l;
if (l & 4) {
avail -= 4;
value = static_cast<T>(loadUnaligned<uint32_t>(cp + avail))
<< (avail * 8);
}
if (l & 2) {
avail -= 2;
value |= static_cast<T>(loadUnaligned<uint16_t>(cp + avail))
<< (avail * 8);
}
if (l & 1) {
value |= loadUnaligned<uint8_t>(cp);
}
return value;
}
template <class T>
inline void storeUnaligned(void* p, T value) {
static_assert(sizeof(Unaligned<T>) == sizeof(T), "Invalid unaligned size");
static_assert(alignof(Unaligned<T>) == 1, "Invalid alignment");
if (kHasUnalignedAccess) {
assume(p != nullptr);
new (p) Unaligned<T>(value);
} else {
memcpy(p, &value, sizeof(T));
}
}
template <typename T>
T bitReverse(T n) {
auto m = static_cast<typename std::make_unsigned<T>::type>(n);
m = ((m & 0xAAAAAAAAAAAAAAAA) >> 1) | ((m & 0x5555555555555555) << 1);
m = ((m & 0xCCCCCCCCCCCCCCCC) >> 2) | ((m & 0x3333333333333333) << 2);
m = ((m & 0xF0F0F0F0F0F0F0F0) >> 4) | ((m & 0x0F0F0F0F0F0F0F0F) << 4);
return static_cast<T>(Endian::swap(m));
}
} // namespace folly
// # 18 "tlm/deps/folly.exploded/include/folly/Bits.h" 2 3 4
// # 43 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
// 2
// # 44 "/mnt/Code/couchbase/docker/platform/include/platform/platform_socket.h"
inline uint64_t ntohll(uint64_t x) {
return folly::Endian::big(x);
}
inline uint64_t htonll(uint64_t x) {
return folly::Endian::big(x);
}
// # 20 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 2
typedef int SOCKET;
// # 1 "tlm/deps/json.exploded/include/nlohmann/json_fwd.hpp" 1 3 4
// # 6 "tlm/deps/json.exploded/include/nlohmann/json_fwd.hpp" 2 3 4
// # 15 "tlm/deps/json.exploded/include/nlohmann/json_fwd.hpp" 3 4
namespace nlohmann {
template <typename T = void, typename SFINAE = void>
struct adl_serializer;
template <template <typename U, typename V, typename... Args> class ObjectType =
std::map,
template <typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string,
class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template <typename U> class AllocatorType = std::allocator,
template <typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer>
class basic_json;
// # 50 "tlm/deps/json.exploded/include/nlohmann/json_fwd.hpp" 3 4
template <typename BasicJsonType>
class json_pointer;
// # 61 "tlm/deps/json.exploded/include/nlohmann/json_fwd.hpp" 3 4
using json = basic_json<>;
} // namespace nlohmann
// # 33 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 2
// # 34 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 2
// # 37 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
namespace cb::net {
int closesocket(SOCKET s);
int get_socket_error();
int bind(SOCKET sock, const struct sockaddr* name, socklen_t namelen);
SOCKET accept(SOCKET sock, struct sockaddr* addr, socklen_t* addrlen);
int connect(SOCKET sock, const struct sockaddr* name, size_t namelen);
SOCKET socket(int domain, int type, int protocol);
int shutdown(SOCKET sock, int how);
ssize_t send(SOCKET sock, const void* buffer, size_t length, int flags);
ssize_t sendmsg(SOCKET sock, const struct msghdr* message, int flags);
ssize_t sendto(SOCKET sock,
const void* buffer,
size_t length,
int flags,
const struct sockaddr* dest_addr,
socklen_t dest_len);
ssize_t recv(SOCKET sock, void* buffer, size_t length, int flags);
ssize_t recvfrom(SOCKET sock,
void* buffer,
size_t length,
int flags,
struct sockaddr* address,
socklen_t* address_len);
ssize_t recvmsg(SOCKET sock, struct msghdr* message, int flags);
int getsockopt(SOCKET sock,
int level,
int option_name,
void* option_value,
socklen_t* option_len);
int setsockopt(SOCKET sock,
int level,
int option_name,
const void* option_value,
socklen_t option_len);
int socketpair(int domain, int type, int protocol, SOCKET socket_vector[2]);
int set_socket_noblocking(SOCKET sock);
int listen(SOCKET sock, int backlog);
// # 117 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
inline int is_blocking(int dw = get_socket_error()) {
return (dw ==
// # 118
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
11
// # 118
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
||
dw ==
// # 118
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
11
// # 118
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
);
}
inline int is_interrupted(int dw = get_socket_error()) {
return (dw ==
// # 121
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
4
// # 121
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
||
dw ==
// # 121
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
11
// # 121
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
);
}
inline int is_emfile(int dw = get_socket_error()) {
return (dw ==
// # 124
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 3
// 4
24
// # 124
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
);
}
inline int is_closed_conn(int dw = get_socket_error()) {
return (dw ==
// # 127
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
107
// # 127
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
||
dw ==
// # 127
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
104
// # 127
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
);
}
inline int is_addrinuse(int dw = get_socket_error()) {
return (dw ==
// # 130
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 3
// 4
98
// # 130
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
);
}
inline void set_ewouldblock() {
// # 133 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 3 4
(*__errno_location())
// # 133
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
=
// # 133
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
11
// # 133
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
;
}
inline void set_econnreset() {
// # 136 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h" 3 4
(*__errno_location())
// # 136
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
=
// # 136
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
// 3 4
104
// # 136
// "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
;
}
std::string to_string(const struct sockaddr_storage* addr, socklen_t addr_len);
nlohmann::json to_json(const struct sockaddr_storage* addr, socklen_t addr_len);
// # 157 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
std::string getsockname(SOCKET sfd);
// # 168 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
nlohmann::json getSockNameAsJson(SOCKET sfd);
// # 180 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
std::string getpeername(SOCKET sfd);
// # 191 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
nlohmann::json getPeerNameAsJson(SOCKET sfd);
// # 200 "/mnt/Code/couchbase/docker/platform/include/platform/socket.h"
std::pair<std::vector<std::string>, std::vector<std::string>> getIpAddresses(
bool skipLoopback);
std::string getHostname();
} // namespace cb::net
// # 15 "/mnt/Code/couchbase/docker/kv_engine/include/memcached/vbucket.h" 2
enum vbucket_state_t : int {
vbucket_state_active = 1,
vbucket_state_replica,
vbucket_state_pending,
vbucket_state_dead
};
enum class RequestedVBState : int {
Alive = 0,
Active = vbucket_state_active,
Replica = vbucket_state_replica,
Pending = vbucket_state_pending,
Dead = vbucket_state_dead,
};
struct vbucket_failover_t {
uint64_t uuid;
uint64_t seqno;
};
class Vbid {
public:
using id_type = uint16_t;
Vbid() = default;
explicit Vbid(id_type vbidParam) : vbid(vbidParam){};
id_type get() const {
return vbid;
}
std::string to_string() const {
return "vb:" + std::to_string(vbid);
}
Vbid ntoh() const {
return Vbid(ntohs(vbid));
}
Vbid hton() const {
return Vbid(htons(vbid));
}
bool operator<(const Vbid& other) const {
return (vbid < other.get());
}
bool operator<=(const Vbid& other) const {
return (vbid <= other.get());
}
bool operator>(const Vbid& other) const {
return (vbid > other.get());
}
bool operator>=(const Vbid& other) const {
return (vbid >= other.get());
}
bool operator==(const Vbid& other) const {
return (vbid == other.get());
}
bool operator!=(const Vbid& other) const {
return (vbid != other.get());
}
Vbid operator++() {
return Vbid(++vbid);
}
Vbid operator++(int) {
return Vbid(vbid++);
}
protected:
id_type vbid;
};
std::ostream& operator<<(std::ostream& os, const Vbid& d);
std::string to_string(const Vbid& vbucket);
namespace std {
template <>
struct hash<Vbid> {
public:
size_t operator()(const Vbid& d) const {
return static_cast<size_t>(d.get());
}
};
} // namespace std
// # 16 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.h" 2
class BucketLogger;
class DcpProducer {
public:
std::shared_ptr<BucketLogger> logger;
void bufferAcknowledgement(uint32_t opaque, Vbid vbucket);
};
// # 13 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc" 2
// # 1 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h" 1
// # 12 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
// # 1 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h" 1
// # 17 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
// # 1 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h" 1
// # 1 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/tweakme.h"
// 1
// # 7 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h" 2
// # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/null_mutex.h"
// 1
// # 7
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/null_mutex.h"
// 2
// # 10
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/null_mutex.h"
namespace spdlog {
namespace details {
struct null_mutex {
void lock() const {
}
void unlock() const {
}
bool try_lock() const {
return true;
}
};
struct null_atomic_int {
int value;
null_atomic_int() = default;
explicit null_atomic_int(int new_value) : value(new_value) {
}
int load(std::memory_order = std::memory_order_relaxed) const {
return value;
}
void store(int new_value, std::memory_order = std::memory_order_relaxed) {
value = new_value;
}
int exchange(int new_value, std::memory_order = std::memory_order_relaxed) {
std::swap(new_value, value);
return new_value;
}
};
} // namespace details
} // namespace spdlog
// # 8 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h" 2
// # 11 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
// 2 # 36
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h" # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/fmt.h" 1
// # 25 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/fmt.h"
// # 1 "tlm/deps/fmt.exploded/include/fmt/core.h" 1 3 4
// # 11 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
// # 12 "tlm/deps/fmt.exploded/include/fmt/core.h" 2 3 4
// # 13 "tlm/deps/fmt.exploded/include/fmt/core.h" 2 3 4
// # 15 "tlm/deps/fmt.exploded/include/fmt/core.h" 2 3 4
// # 255 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
namespace fmt {
inline namespace v7 {
template <bool B, class T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template <bool B, class T, class F>
using conditional_t = typename std::conditional<B, T, F>::type;
template <bool B>
using bool_constant = std::integral_constant<bool, B>;
template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;
template <typename T>
using remove_const_t = typename std::remove_const<T>::type;
template <typename T>
using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
template <typename T>
struct type_identity {
using type = T;
};
template <typename T>
using type_identity_t = typename type_identity<T>::type;
struct monostate {};
namespace detail {
template <typename T>
constexpr T const_check(T value) {
return value;
}
[[noreturn]] void assert_fail(const char* file, int line, const char* message);
// # 300 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Char>
using std_string_view = std::basic_string_view<Char>;
// # 313 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
using int128_t = __int128_t;
using uint128_t = __uint128_t;
// # 324 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Int>
constexpr typename std::make_unsigned<Int>::type to_unsigned(Int value) {
((value >= 0) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/core.h",
326,
("negative value")));
return static_cast<typename std::make_unsigned<Int>::type>(value);
}
constexpr unsigned char micro[] = "\u00B5";
template <typename Char>
constexpr bool is_unicode() {
return !0 || sizeof(Char) != 1 ||
(sizeof(micro) == 3 && micro[0] == 0xC2 && micro[1] == 0xB5);
}
enum char8_type : unsigned char {};
} // namespace detail
// # 355 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Char>
class basic_string_view {
private:
const Char* data_;
size_t size_;
public:
using value_type = Char;
using iterator = const Char*;
constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {
}
constexpr basic_string_view(const Char* s, size_t count) noexcept
: data_(s), size_(count) {
}
// # 378 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
constexpr
basic_string_view(const Char* s)
: data_(s), size_(std::char_traits<Char>::length(s)) {
}
template <typename Traits, typename Alloc>
constexpr basic_string_view(
const std::basic_string<Char, Traits, Alloc>& s) noexcept
: data_(s.data()), size_(s.size()) {
}
template <
typename S,
enable_if_t<(std::is_same<S, detail::std_string_view<Char>>::value),
int> = 0>
constexpr basic_string_view(S s) noexcept
: data_(s.data()), size_(s.size()) {
}
constexpr const Char* data() const {
return data_;
}
constexpr size_t size() const {
return size_;
}
constexpr iterator begin() const {
return data_;
}
constexpr iterator end() const {
return data_ + size_;
}
constexpr const Char& operator[](size_t pos) const {
return data_[pos];
}
constexpr void remove_prefix(size_t n) {
data_ += n;
size_ -= n;
}
int compare(basic_string_view other) const {
size_t str_size = size_ < other.size_ ? size_ : other.size_;
int result =
std::char_traits<Char>::compare(data_, other.data_, str_size);
if (result == 0)
result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
return result;
}
friend bool operator==(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) == 0;
}
friend bool operator!=(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) != 0;
}
friend bool operator<(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) < 0;
}
friend bool operator<=(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) <= 0;
}
friend bool operator>(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) > 0;
}
friend bool operator>=(basic_string_view lhs, basic_string_view rhs) {
return lhs.compare(rhs) >= 0;
}
};
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
template <typename T>
struct is_char : std::false_type {};
template <>
struct is_char<char> : std::true_type {};
template <>
struct is_char<wchar_t> : std::true_type {};
template <>
struct is_char<detail::char8_type> : std::true_type {};
template <>
struct is_char<char16_t> : std::true_type {};
template <>
struct is_char<char32_t> : std::true_type {};
// # 467 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Char, enable_if_t<(is_char<Char>::value), int> = 0>
inline basic_string_view<Char> to_string_view(const Char* s) {
return s;
}
template <typename Char, typename Traits, typename Alloc>
inline basic_string_view<Char> to_string_view(
const std::basic_string<Char, Traits, Alloc>& s) {
return s;
}
template <typename Char>
inline basic_string_view<Char> to_string_view(basic_string_view<Char> s) {
return s;
}
template <typename Char,
enable_if_t<(!std::is_empty<detail::std_string_view<Char>>::value),
int> = 0>
inline basic_string_view<Char> to_string_view(detail::std_string_view<Char> s) {
return s;
}
struct compile_string {};
template <typename S>
struct is_compile_string : std::is_base_of<compile_string, S> {};
template <typename S, enable_if_t<(is_compile_string<S>::value), int> = 0>
constexpr basic_string_view<typename S::char_type> to_string_view(const S& s) {
return s;
}
namespace detail {
void to_string_view(...);
using fmt::v7::to_string_view;
template <typename S>
struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {
};
template <typename S, typename = void>
struct char_t_impl {};
template <typename S>
struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
using result = decltype(to_string_view(std::declval<S>()));
using type = typename result::value_type;
};
template <typename...,
typename S,
enable_if_t<(!is_compile_string<S>::value), int> = 0>
inline __attribute__((always_inline)) void check_format_string(const S&) {
}
template <typename...,
typename S,
enable_if_t<(is_compile_string<S>::value), int> = 0>
void check_format_string(S);
struct error_handler {
constexpr error_handler() = default;
constexpr error_handler(const error_handler&) = default;
[[noreturn]] void on_error(const char* message);
};
} // namespace detail
template <typename S>
using char_t = typename detail::char_t_impl<S>::type;
// # 558 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Char, typename ErrorHandler = detail::error_handler>
class basic_format_parse_context : private ErrorHandler {
private:
basic_string_view<Char> format_str_;
int next_arg_id_;
public:
using char_type = Char;
using iterator = typename basic_string_view<Char>::iterator;
explicit constexpr basic_format_parse_context(
basic_string_view<Char> format_str,
ErrorHandler eh = {},
int next_arg_id = 0)
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {
}
constexpr iterator begin() const noexcept {
return format_str_.begin();
}
constexpr iterator end() const noexcept {
return format_str_.end();
}
constexpr void advance_to(iterator it) {
format_str_.remove_prefix(detail::to_unsigned(it - begin()));
}
constexpr int next_arg_id() {
if (next_arg_id_ >= 0)
return next_arg_id_++;
on_error("cannot switch from manual to automatic argument indexing");
return 0;
}
constexpr void check_arg_id(int) {
if (next_arg_id_ > 0)
on_error(
"cannot switch from automatic to manual argument indexing");
else
next_arg_id_ = -1;
}
constexpr void check_arg_id(basic_string_view<Char>) {
}
constexpr void on_error(const char* message) {
ErrorHandler::on_error(message);
}
constexpr ErrorHandler error_handler() const {
return *this;
}
};
using format_parse_context = basic_format_parse_context<char>;
using wformat_parse_context = basic_format_parse_context<wchar_t>;
template <typename Context>
class basic_format_arg;
template <typename Context>
class basic_format_args;
template <typename Context>
class dynamic_format_arg_store;
template <typename T, typename Char = char, typename Enable = void>
struct formatter {
formatter() = delete;
};
template <typename T, typename Context>
using has_formatter =
std::is_constructible<typename Context::template formatter_type<T>>;
template <typename T>
struct is_contiguous : std::false_type {};
template <typename Char>
struct is_contiguous<std::basic_string<Char>> : std::true_type {};
namespace detail {
template <typename Container>
inline Container& get_container(std::back_insert_iterator<Container> it) {
using bi_iterator = std::back_insert_iterator<Container>;
struct accessor : bi_iterator {
accessor(bi_iterator iter) : bi_iterator(iter) {
}
using bi_iterator::container;
};
return *accessor(it).container;
}
template <typename T>
class buffer {
private:
T* ptr_;
size_t size_;
size_t capacity_;
protected:
buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {
}
buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
: ptr_(p), size_(sz), capacity_(cap) {
}
~buffer() = default;
void set(T* buf_data, size_t buf_capacity) noexcept {
ptr_ = buf_data;
capacity_ = buf_capacity;
}
virtual void grow(size_t capacity) = 0;
public:
using value_type = T;
using const_reference = const T&;
buffer(const buffer&) = delete;
void operator=(const buffer&) = delete;
T* begin() noexcept {
return ptr_;
}
T* end() noexcept {
return ptr_ + size_;
}
const T* begin() const noexcept {
return ptr_;
}
const T* end() const noexcept {
return ptr_ + size_;
}
size_t size() const noexcept {
return size_;
}
size_t capacity() const noexcept {
return capacity_;
}
T* data() noexcept {
return ptr_;
}
const T* data() const noexcept {
return ptr_;
}
void clear() {
size_ = 0;
}
void try_resize(size_t count) {
try_reserve(count);
size_ = count <= capacity_ ? count : capacity_;
}
void try_reserve(size_t new_capacity) {
if (new_capacity > capacity_)
grow(new_capacity);
}
void push_back(const T& value) {
try_reserve(size_ + 1);
ptr_[size_++] = value;
}
template <typename U>
void append(const U* begin, const U* end);
template <typename I>
T& operator[](I index) {
return ptr_[index];
}
template <typename I>
const T& operator[](I index) const {
return ptr_[index];
}
};
struct buffer_traits {
explicit buffer_traits(size_t) {
}
size_t count() const {
return 0;
}
size_t limit(size_t size) {
return size;
}
};
class fixed_buffer_traits {
private:
size_t count_ = 0;
size_t limit_;
public:
explicit fixed_buffer_traits(size_t limit) : limit_(limit) {
}
size_t count() const {
return count_;
}
size_t limit(size_t size) {
size_t n = limit_ > count_ ? limit_ - count_ : 0;
count_ += size;
return size < n ? size : n;
}
};
template <typename OutputIt, typename T, typename Traits = buffer_traits>
class iterator_buffer final : public Traits, public buffer<T> {
private:
OutputIt out_;
enum { buffer_size = 256 };
T data_[buffer_size];
protected:
void grow(size_t) final override {
if (this->size() == buffer_size)
flush();
}
void flush();
public:
explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
: Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {
}
~iterator_buffer() {
flush();
}
OutputIt out() {
flush();
return out_;
}
size_t count() const {
return Traits::count() + this->size();
}
};
template <typename T>
class iterator_buffer<T*, T> final : public buffer<T> {
protected:
void grow(size_t) final override {
}
public:
explicit iterator_buffer(T* out, size_t = 0)
: buffer<T>(out, 0, ~size_t()) {
}
T* out() {
return &*this->end();
}
};
template <typename Container>
class iterator_buffer<std::back_insert_iterator<Container>,
enable_if_t<is_contiguous<Container>::value,
typename Container::value_type>>
final : public buffer<typename Container::value_type> {
private:
Container& container_;
protected:
void grow(size_t capacity) final override {
container_.resize(capacity);
this->set(&container_[0], capacity);
}
public:
explicit iterator_buffer(Container& c)
: buffer<typename Container::value_type>(c.size()), container_(c) {
}
explicit iterator_buffer(std::back_insert_iterator<Container> out,
size_t = 0)
: iterator_buffer(get_container(out)) {
}
std::back_insert_iterator<Container> out() {
return std::back_inserter(container_);
}
};
template <typename T = char>
class counting_buffer final : public buffer<T> {
private:
enum { buffer_size = 256 };
T data_[buffer_size];
size_t count_ = 0;
protected:
void grow(size_t) final override {
if (this->size() != buffer_size)
return;
count_ += this->size();
this->clear();
}
public:
counting_buffer() : buffer<T>(data_, 0, buffer_size) {
}
size_t count() {
return count_ + this->size();
}
};
template <typename T>
class buffer_appender : public std::back_insert_iterator<buffer<T>> {
using base = std::back_insert_iterator<buffer<T>>;
public:
explicit buffer_appender(buffer<T>& buf) : base(buf) {
}
buffer_appender(base it) : base(it) {
}
buffer_appender& operator++() {
base::operator++();
return *this;
}
buffer_appender operator++(int) {
buffer_appender tmp = *this;
++*this;
return tmp;
}
};
template <typename T, typename OutputIt>
iterator_buffer<OutputIt, T> get_buffer(OutputIt);
template <typename T>
buffer<T>& get_buffer(buffer_appender<T>);
template <typename OutputIt>
OutputIt get_buffer_init(OutputIt out) {
return out;
}
template <typename T>
buffer<T>& get_buffer_init(buffer_appender<T> out) {
return get_container(out);
}
template <typename Buffer>
auto get_iterator(Buffer& buf) -> decltype(buf.out()) {
return buf.out();
}
template <typename T>
buffer_appender<T> get_iterator(buffer<T>& buf) {
return buffer_appender<T>(buf);
}
template <typename T, typename Char = char, typename Enable = void>
struct fallback_formatter {
fallback_formatter() = delete;
};
template <typename T, typename Context>
using has_fallback_formatter = std::is_constructible<
fallback_formatter<T, typename Context::char_type>>;
struct view {};
template <typename Char, typename T>
struct named_arg : view {
const Char* name;
const T& value;
named_arg(const Char* n, const T& v) : name(n), value(v) {
}
};
template <typename Char>
struct named_arg_info {
const Char* name;
int id;
};
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
struct arg_data {
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
template <typename... U>
arg_data(const U&... init)
: args_{T(named_args_, NUM_NAMED_ARGS), init...} {
}
arg_data(const arg_data& other) = delete;
const T* args() const {
return args_ + 1;
}
named_arg_info<Char>* named_args() {
return named_args_;
}
};
template <typename T, typename Char, size_t NUM_ARGS>
struct arg_data<T, Char, NUM_ARGS, 0> {
T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
template <typename... U>
inline __attribute__((always_inline)) arg_data(const U&... init)
: args_{init...} {
}
inline __attribute__((always_inline)) const T* args() const {
return args_;
}
inline __attribute__((always_inline)) std::nullptr_t named_args() {
return nullptr;
}
};
template <typename Char>
inline void init_named_args(named_arg_info<Char>*, int, int) {
}
template <typename Char, typename T, typename... Tail>
void init_named_args(named_arg_info<Char>* named_args,
int arg_count,
int named_arg_count,
const T&,
const Tail&... args) {
init_named_args(named_args, arg_count + 1, named_arg_count, args...);
}
template <typename Char, typename T, typename... Tail>
void init_named_args(named_arg_info<Char>* named_args,
int arg_count,
int named_arg_count,
const named_arg<Char, T>& arg,
const Tail&... args) {
named_args[named_arg_count++] = {arg.name, arg_count};
init_named_args(named_args, arg_count + 1, named_arg_count, args...);
}
template <typename... Args>
inline __attribute__((always_inline)) void init_named_args(std::nullptr_t,
int,
int,
const Args&...) {
}
template <typename T>
struct is_named_arg : std::false_type {};
template <typename T, typename Char>
struct is_named_arg<named_arg<Char, T>> : std::true_type {};
template <bool B = false>
constexpr size_t count() {
return B ? 1 : 0;
}
template <bool B1, bool B2, bool... Tail>
constexpr size_t count() {
return (B1 ? 1 : 0) + count<B2, Tail...>();
}
template <typename... Args>
constexpr size_t count_named_args() {
return count<is_named_arg<Args>::value...>();
}
enum class type {
none_type,
int_type,
uint_type,
long_long_type,
ulong_long_type,
int128_type,
uint128_type,
bool_type,
char_type,
last_integer_type = char_type,
float_type,
double_type,
long_double_type,
last_numeric_type = long_double_type,
cstring_type,
string_type,
pointer_type,
custom_type
};
template <typename T, typename Char>
struct type_constant : std::integral_constant<type, type::custom_type> {};
template <typename Char>
struct type_constant<int, Char> : std::integral_constant<type, type::int_type> {
};
template <typename Char>
struct type_constant<unsigned, Char>
: std::integral_constant<type, type::uint_type> {};
template <typename Char>
struct type_constant<long long, Char>
: std::integral_constant<type, type::long_long_type> {};
template <typename Char>
struct type_constant<unsigned long long, Char>
: std::integral_constant<type, type::ulong_long_type> {};
template <typename Char>
struct type_constant<int128_t, Char>
: std::integral_constant<type, type::int128_type> {};
template <typename Char>
struct type_constant<uint128_t, Char>
: std::integral_constant<type, type::uint128_type> {};
template <typename Char>
struct type_constant<bool, Char>
: std::integral_constant<type, type::bool_type> {};
template <typename Char>
struct type_constant<Char, Char>
: std::integral_constant<type, type::char_type> {};
template <typename Char>
struct type_constant<float, Char>
: std::integral_constant<type, type::float_type> {};
template <typename Char>
struct type_constant<double, Char>
: std::integral_constant<type, type::double_type> {};
template <typename Char>
struct type_constant<long double, Char>
: std::integral_constant<type, type::long_double_type> {};
template <typename Char>
struct type_constant<const Char*, Char>
: std::integral_constant<type, type::cstring_type> {};
template <typename Char>
struct type_constant<basic_string_view<Char>, Char>
: std::integral_constant<type, type::string_type> {};
template <typename Char>
struct type_constant<const void*, Char>
: std::integral_constant<type, type::pointer_type> {};
constexpr bool is_integral_type(type t) {
return t > type::none_type && t <= type::last_integer_type;
}
constexpr bool is_arithmetic_type(type t) {
return t > type::none_type && t <= type::last_numeric_type;
}
template <typename Char>
struct string_value {
const Char* data;
size_t size;
};
template <typename Char>
struct named_arg_value {
const named_arg_info<Char>* data;
size_t size;
};
template <typename Context>
struct custom_value {
using parse_context = typename Context::parse_context_type;
const void* value;
void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx);
};
template <typename Context>
class value {
public:
using char_type = typename Context::char_type;
union {
int int_value;
unsigned uint_value;
long long long_long_value;
unsigned long long ulong_long_value;
int128_t int128_value;
uint128_t uint128_value;
bool bool_value;
char_type char_value;
float float_value;
double double_value;
long double long_double_value;
const void* pointer;
string_value<char_type> string;
custom_value<Context> custom;
named_arg_value<char_type> named_args;
};
constexpr inline __attribute__((always_inline)) value(int val = 0)
: int_value(val) {
}
constexpr inline __attribute__((always_inline)) value(unsigned val)
: uint_value(val) {
}
inline __attribute__((always_inline)) value(long long val)
: long_long_value(val) {
}
inline __attribute__((always_inline)) value(unsigned long long val)
: ulong_long_value(val) {
}
inline __attribute__((always_inline)) value(int128_t val)
: int128_value(val) {
}
inline __attribute__((always_inline)) value(uint128_t val)
: uint128_value(val) {
}
inline __attribute__((always_inline)) value(float val) : float_value(val) {
}
inline __attribute__((always_inline)) value(double val)
: double_value(val) {
}
inline __attribute__((always_inline)) value(long double val)
: long_double_value(val) {
}
inline __attribute__((always_inline)) value(bool val) : bool_value(val) {
}
inline __attribute__((always_inline)) value(char_type val)
: char_value(val) {
}
inline __attribute__((always_inline)) value(const char_type* val) {
string.data = val;
}
inline __attribute__((always_inline))
value(basic_string_view<char_type> val) {
string.data = val.data();
string.size = val.size();
}
inline __attribute__((always_inline)) value(const void* val)
: pointer(val) {
}
inline __attribute__((always_inline))
value(const named_arg_info<char_type>* args, size_t size)
: named_args{args, size} {
}
template <typename T>
inline __attribute__((always_inline)) value(const T& val) {
custom.value = &val;
custom.format = format_custom_arg<
T,
conditional_t<has_formatter<T, Context>::value,
typename Context::template formatter_type<T>,
fallback_formatter<T, char_type>>>;
}
private:
template <typename T, typename Formatter>
static void format_custom_arg(
const void* arg,
typename Context::parse_context_type& parse_ctx,
Context& ctx) {
Formatter f;
parse_ctx.advance_to(f.parse(parse_ctx));
ctx.advance_to(f.format(*static_cast<const T*>(arg), ctx));
}
};
template <typename Context, typename T>
constexpr basic_format_arg<Context> make_arg(const T& value);
enum { long_short = sizeof(long) == sizeof(int) };
using long_type = conditional_t<long_short, int, long long>;
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
struct unformattable {};
template <typename Context>
struct arg_mapper {
using char_type = typename Context::char_type;
constexpr int map(signed char val) {
return val;
}
constexpr unsigned map(unsigned char val) {
return val;
}
constexpr int map(short val) {
return val;
}
constexpr unsigned map(unsigned short val) {
return val;
}
constexpr int map(int val) {
return val;
}
constexpr unsigned map(unsigned val) {
return val;
}
constexpr long_type map(long val) {
return val;
}
constexpr ulong_type map(unsigned long val) {
return val;
}
constexpr long long map(long long val) {
return val;
}
constexpr unsigned long long map(unsigned long long val) {
return val;
}
constexpr int128_t map(int128_t val) {
return val;
}
constexpr uint128_t map(uint128_t val) {
return val;
}
constexpr bool map(bool val) {
return val;
}
template <typename T, enable_if_t<(is_char<T>::value), int> = 0>
constexpr char_type map(T val) {
static_assert(std::is_same<T, char>::value ||
std::is_same<T, char_type>::value,
"mixing character types is disallowed");
return val;
}
constexpr float map(float val) {
return val;
}
constexpr double map(double val) {
return val;
}
constexpr long double map(long double val) {
return val;
}
constexpr const char_type* map(char_type* val) {
return val;
}
constexpr const char_type* map(const char_type* val) {
return val;
}
template <typename T, enable_if_t<(is_string<T>::value), int> = 0>
constexpr basic_string_view<char_type> map(const T& val) {
static_assert(std::is_same<char_type, char_t<T>>::value,
"mixing character types is disallowed");
return to_string_view(val);
}
template <typename T,
enable_if_t<(std::is_constructible<basic_string_view<char_type>,
T>::value &&
!is_string<T>::value &&
!has_formatter<T, Context>::value &&
!has_fallback_formatter<T, Context>::value),
int> = 0
>
constexpr basic_string_view<char_type> map(const T& val) {
return basic_string_view<char_type>(val);
}
template <typename T,
enable_if_t<(std::is_constructible<std_string_view<char_type>,
T>::value &&
!std::is_constructible<basic_string_view<char_type>,
T>::value &&
!is_string<T>::value &&
!has_formatter<T, Context>::value &&
!has_fallback_formatter<T, Context>::value),
int> = 0
>
constexpr basic_string_view<char_type> map(const T& val) {
return std_string_view<char_type>(val);
}
constexpr const char* map(const signed char* val) {
static_assert(std::is_same<char_type, char>::value,
"invalid string type");
return reinterpret_cast<const char*>(val);
}
constexpr const char* map(const unsigned char* val) {
static_assert(std::is_same<char_type, char>::value,
"invalid string type");
return reinterpret_cast<const char*>(val);
}
constexpr const char* map(signed char* val) {
const auto* const_val = val;
return map(const_val);
}
constexpr const char* map(unsigned char* val) {
const auto* const_val = val;
return map(const_val);
}
constexpr const void* map(void* val) {
return val;
}
constexpr const void* map(const void* val) {
return val;
}
constexpr const void* map(std::nullptr_t val) {
return val;
}
template <typename T>
constexpr int map(const T*) {
static_assert(!sizeof(T),
"formatting of non-void pointers is disallowed");
return 0;
}
template <typename T,
enable_if_t<(std::is_enum<T>::value &&
!has_formatter<T, Context>::value &&
!has_fallback_formatter<T, Context>::value),
int> = 0
>
constexpr auto map(const T& val) -> decltype(std::declval<arg_mapper>().map(
static_cast<typename std::underlying_type<T>::type>(val))) {
return map(static_cast<typename std::underlying_type<T>::type>(val));
}
template <typename T,
enable_if_t<(!is_string<T>::value && !is_char<T>::value &&
(has_formatter<T, Context>::value ||
has_fallback_formatter<T, Context>::value)),
int> = 0
>
constexpr const T& map(const T& val) {
return val;
}
template <typename T>
constexpr auto map(const named_arg<char_type, T>& val)
-> decltype(std::declval<arg_mapper>().map(val.value)) {
return map(val.value);
}
unformattable map(...) {
return {};
}
};
template <typename T, typename Context>
using mapped_type_constant = type_constant<decltype(arg_mapper<Context>().map(
std::declval<const T&>())),
typename Context::char_type>;
enum { packed_arg_bits = 4 };
enum { max_packed_args = 62 / packed_arg_bits };
enum : unsigned long long { is_unpacked_bit = 1ULL << 63 };
enum : unsigned long long { has_named_args_bit = 1ULL << 62 };
} // namespace detail
template <typename Context>
class basic_format_arg {
private:
detail::value<Context> value_;
detail::type type_;
template <typename ContextType, typename T>
friend constexpr basic_format_arg<ContextType> detail::make_arg(
const T& value);
template <typename Visitor, typename Ctx>
friend constexpr auto visit_format_arg(Visitor&& vis,
const basic_format_arg<Ctx>& arg)
-> decltype(vis(0));
friend class basic_format_args<Context>;
friend class dynamic_format_arg_store<Context>;
using char_type = typename Context::char_type;
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
friend struct detail::arg_data;
basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
: value_(args, size) {
}
public:
class handle {
public:
explicit handle(detail::custom_value<Context> custom)
: custom_(custom) {
}
void format(typename Context::parse_context_type& parse_ctx,
Context& ctx) const {
custom_.format(custom_.value, parse_ctx, ctx);
}
private:
detail::custom_value<Context> custom_;
};
constexpr basic_format_arg() : type_(detail::type::none_type) {
}
constexpr explicit operator bool() const noexcept {
return type_ != detail::type::none_type;
}
detail::type type() const {
return type_;
}
bool is_integral() const {
return detail::is_integral_type(type_);
}
bool is_arithmetic() const {
return detail::is_arithmetic_type(type_);
}
};
// # 1309 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Visitor, typename Context>
constexpr inline __attribute__((always_inline)) auto visit_format_arg(
Visitor&& vis, const basic_format_arg<Context>& arg)
-> decltype(vis(0)) {
using char_type = typename Context::char_type;
switch (arg.type_) {
case detail::type::none_type:
break;
case detail::type::int_type:
return vis(arg.value_.int_value);
case detail::type::uint_type:
return vis(arg.value_.uint_value);
case detail::type::long_long_type:
return vis(arg.value_.long_long_value);
case detail::type::ulong_long_type:
return vis(arg.value_.ulong_long_value);
case detail::type::int128_type:
return vis(arg.value_.int128_value);
case detail::type::uint128_type:
return vis(arg.value_.uint128_value);
case detail::type::bool_type:
return vis(arg.value_.bool_value);
case detail::type::char_type:
return vis(arg.value_.char_value);
case detail::type::float_type:
return vis(arg.value_.float_value);
case detail::type::double_type:
return vis(arg.value_.double_value);
case detail::type::long_double_type:
return vis(arg.value_.long_double_value);
case detail::type::cstring_type:
return vis(arg.value_.string.data);
case detail::type::string_type:
return vis(basic_string_view<char_type>(arg.value_.string.data,
arg.value_.string.size));
case detail::type::pointer_type:
return vis(arg.value_.pointer);
case detail::type::custom_type:
return vis(
typename basic_format_arg<Context>::handle(arg.value_.custom));
}
return vis(monostate());
}
template <typename T>
struct formattable : std::false_type {};
namespace detail {
template <typename... Ts>
struct void_t_impl {
using type = void;
};
template <typename... Ts>
using void_t = typename detail::void_t_impl<Ts...>::type;
template <typename It, typename T, typename Enable = void>
struct is_output_iterator : std::false_type {};
template <typename It, typename T>
struct is_output_iterator<
It,
T,
void_t<typename std::iterator_traits<It>::iterator_category,
decltype(*std::declval<It>() = std::declval<T>())>>
: std::true_type {};
template <typename OutputIt>
struct is_back_insert_iterator : std::false_type {};
template <typename Container>
struct is_back_insert_iterator<std::back_insert_iterator<Container>>
: std::true_type {};
template <typename OutputIt>
struct is_contiguous_back_insert_iterator : std::false_type {};
template <typename Container>
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
: is_contiguous<Container> {};
template <typename Char>
struct is_contiguous_back_insert_iterator<buffer_appender<Char>>
: std::true_type {};
class locale_ref {
private:
const void* locale_;
public:
locale_ref() : locale_(nullptr) {
}
template <typename Locale>
explicit locale_ref(const Locale& loc);
explicit operator bool() const noexcept {
return locale_ != nullptr;
}
template <typename Locale>
Locale get() const;
};
template <typename>
constexpr unsigned long long encode_types() {
return 0;
}
template <typename Context, typename Arg, typename... Args>
constexpr unsigned long long encode_types() {
return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
(encode_types<Context, Args...>() << packed_arg_bits);
}
template <typename Context, typename T>
constexpr basic_format_arg<Context> make_arg(const T& value) {
basic_format_arg<Context> arg;
arg.type_ = mapped_type_constant<T, Context>::value;
arg.value_ = arg_mapper<Context>().map(value);
return arg;
}
template <typename T>
int check(unformattable) {
static_assert(
formattable<T>(),
"Cannot format an argument. To make type T formattable provide a "
"formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
return 0;
}
template <typename T, typename U>
inline const U& check(const U& val) {
return val;
}
template <bool IS_PACKED,
typename Context,
type,
typename T,
enable_if_t<(IS_PACKED), int> = 0>
inline value<Context> make_arg(const T& val) {
return check<T>(arg_mapper<Context>().map(val));
}
template <bool IS_PACKED,
typename Context,
type,
typename T,
enable_if_t<(!IS_PACKED), int> = 0>
inline basic_format_arg<Context> make_arg(const T& value) {
return make_arg<Context>(value);
}
template <typename T>
struct is_reference_wrapper : std::false_type {};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
template <typename T>
const T& unwrap(const T& v) {
return v;
}
template <typename T>
const T& unwrap(const std::reference_wrapper<T>& v) {
return static_cast<const T&>(v);
}
class dynamic_arg_list {
template <typename = void>
struct node {
virtual ~node() = default;
std::unique_ptr<node<>> next;
};
template <typename T>
struct typed_node : node<> {
T value;
template <typename Arg>
constexpr typed_node(const Arg& arg) : value(arg) {
}
template <typename Char>
constexpr typed_node(const basic_string_view<Char>& arg)
: value(arg.data(), arg.size()) {
}
};
std::unique_ptr<node<>> head_;
public:
template <typename T, typename Arg>
const T& push(const Arg& arg) {
auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg));
auto& value = new_node->value;
new_node->next = std::move(head_);
head_ = std::move(new_node);
return value;
}
};
} // namespace detail
template <typename OutputIt, typename Char>
class basic_format_context {
public:
using char_type = Char;
private:
OutputIt out_;
basic_format_args<basic_format_context> args_;
detail::locale_ref loc_;
public:
using iterator = OutputIt;
using format_arg = basic_format_arg<basic_format_context>;
using parse_context_type = basic_format_parse_context<Char>;
template <typename T>
using formatter_type = formatter<T, char_type>;
basic_format_context(const basic_format_context&) = delete;
void operator=(const basic_format_context&) = delete;
basic_format_context(OutputIt out,
basic_format_args<basic_format_context> ctx_args,
detail::locale_ref loc = detail::locale_ref())
: out_(out), args_(ctx_args), loc_(loc) {
}
format_arg arg(int id) const {
return args_.get(id);
}
format_arg arg(basic_string_view<char_type> name) {
return args_.get(name);
}
int arg_id(basic_string_view<char_type> name) {
return args_.get_id(name);
}
const basic_format_args<basic_format_context>& args() const {
return args_;
}
detail::error_handler error_handler() {
return {};
}
void on_error(const char* message) {
error_handler().on_error(message);
}
iterator out() {
return out_;
}
void advance_to(iterator it) {
if (!detail::is_back_insert_iterator<iterator>())
out_ = it;
}
detail::locale_ref locale() {
return loc_;
}
};
template <typename Char>
using buffer_context =
basic_format_context<detail::buffer_appender<Char>, Char>;
using format_context = buffer_context<char>;
using wformat_context = buffer_context<wchar_t>;
// # 1553 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Context, typename... Args>
class format_arg_store
{
private:
static const size_t num_args = sizeof...(Args);
static const size_t num_named_args = detail::count_named_args<Args...>();
static const bool is_packed = num_args <= detail::max_packed_args;
using value_type = conditional_t<is_packed,
detail::value<Context>,
basic_format_arg<Context>>;
detail::arg_data<value_type,
typename Context::char_type,
num_args,
num_named_args>
data_;
friend class basic_format_args<Context>;
static constexpr unsigned long long desc =
(is_packed ? detail::encode_types<Context, Args...>()
: detail::is_unpacked_bit | num_args) |
(num_named_args != 0 ? static_cast<unsigned long long>(
detail::has_named_args_bit)
: 0);
public:
format_arg_store(const Args&... args)
:
data_{detail::make_arg<
is_packed,
Context,
detail::mapped_type_constant<Args, Context>::value>(
args)...} {
detail::init_named_args(data_.named_args(), 0, 0, args...);
}
};
// # 1602 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Context = format_context, typename... Args>
inline format_arg_store<Context, Args...> make_format_args(
const Args&... args) {
return {args...};
}
// # 1616 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename... Args, typename S, typename Char = char_t<S>>
inline auto make_args_checked(const S& format_str,
const remove_reference_t<Args>&... args)
-> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
static_assert(
detail::count<(std::is_base_of<detail::view,
remove_reference_t<Args>>::value &&
std::is_reference<Args>::value)...>() == 0,
"passing views as lvalues is disallowed");
detail::check_format_string<Args...>(format_str);
return {args...};
}
// # 1639 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Char, typename T>
inline detail::named_arg<Char, T> arg(const Char* name, const T& arg) {
static_assert(!detail::is_named_arg<T>(), "nested named arguments");
return {name, arg};
}
// # 1655 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Context>
class dynamic_format_arg_store
{
private:
using char_type = typename Context::char_type;
template <typename T>
struct need_copy {
static constexpr detail::type mapped_type =
detail::mapped_type_constant<T, Context>::value;
enum {
value = !(detail::is_reference_wrapper<T>::value ||
std::is_same<T, basic_string_view<char_type>>::value ||
std::is_same<T,
detail::std_string_view<char_type>>::value ||
(mapped_type != detail::type::cstring_type &&
mapped_type != detail::type::string_type &&
mapped_type != detail::type::custom_type))
};
};
template <typename T>
using stored_type = conditional_t<detail::is_string<T>::value,
std::basic_string<char_type>,
T>;
std::vector<basic_format_arg<Context>> data_;
std::vector<detail::named_arg_info<char_type>> named_info_;
detail::dynamic_arg_list dynamic_args_;
friend class basic_format_args<Context>;
unsigned long long get_types() const {
return detail::is_unpacked_bit | data_.size() |
(named_info_.empty() ? 0ULL
: static_cast<unsigned long long>(
detail::has_named_args_bit));
}
const basic_format_arg<Context>* data() const {
return named_info_.empty() ? data_.data() : data_.data() + 1;
}
template <typename T>
void emplace_arg(const T& arg) {
data_.emplace_back(detail::make_arg<Context>(arg));
}
template <typename T>
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
if (named_info_.empty()) {
constexpr const detail::named_arg_info<char_type>* zero_ptr{
nullptr};
data_.insert(data_.begin(), {zero_ptr, 0});
}
data_.emplace_back(
detail::make_arg<Context>(detail::unwrap(arg.value)));
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
data->pop_back();
};
std::unique_ptr<std::vector<basic_format_arg<Context>>,
decltype(pop_one)>
guard{&data_, pop_one};
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
guard.release();
}
public:
// # 1743 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename T>
void push_back(const T& arg) {
if (detail::const_check(need_copy<T>::value))
emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
else
emplace_arg(detail::unwrap(arg));
}
// # 1772 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename T>
void push_back(std::reference_wrapper<T> arg) {
static_assert(
detail::is_named_arg<typename std::remove_cv<T>::type>::value ||
need_copy<T>::value,
"objects of built-in types and string views are always copied");
emplace_arg(arg.get());
}
template <typename T>
void push_back(const detail::named_arg<char_type, T>& arg) {
const char_type* arg_name =
dynamic_args_.push<std::basic_string<char_type>>(arg.name)
.c_str();
if (detail::const_check(need_copy<T>::value)) {
emplace_arg(fmt::arg(
arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
} else {
emplace_arg(fmt::arg(arg_name, arg.value));
}
}
void clear() {
data_.clear();
named_info_.clear();
dynamic_args_ = detail::dynamic_arg_list();
}
void reserve(size_t new_cap, size_t new_cap_named) {
((new_cap >= new_cap_named)
? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/core.h",
1811,
("Set of arguments includes set of named "
"arguments")));
data_.reserve(new_cap);
named_info_.reserve(new_cap_named);
}
};
// # 1828 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename Context>
class basic_format_args {
public:
using size_type = int;
using format_arg = basic_format_arg<Context>;
private:
unsigned long long desc_;
union {
const detail::value<Context>* values_;
const format_arg* args_;
};
bool is_packed() const {
return (desc_ & detail::is_unpacked_bit) == 0;
}
bool has_named_args() const {
return (desc_ & detail::has_named_args_bit) != 0;
}
detail::type type(int index) const {
int shift = index * detail::packed_arg_bits;
unsigned int mask = (1 << detail::packed_arg_bits) - 1;
return static_cast<detail::type>((desc_ >> shift) & mask);
}
basic_format_args(unsigned long long desc,
const detail::value<Context>* values)
: desc_(desc), values_(values) {
}
basic_format_args(unsigned long long desc, const format_arg* args)
: desc_(desc), args_(args) {
}
public:
basic_format_args() : desc_(0) {
}
template <typename... Args>
inline __attribute__((always_inline))
basic_format_args(const format_arg_store<Context, Args...>& store)
: basic_format_args(store.desc, store.data_.args()) {
}
inline __attribute__((always_inline))
basic_format_args(const dynamic_format_arg_store<Context>& store)
: basic_format_args(store.get_types(), store.data()) {
}
basic_format_args(const format_arg* args, int count)
: basic_format_args(
detail::is_unpacked_bit | detail::to_unsigned(count), args) {
}
format_arg get(int id) const {
format_arg arg;
if (!is_packed()) {
if (id < max_size())
arg = args_[id];
return arg;
}
if (id >= detail::max_packed_args)
return arg;
arg.type_ = type(id);
if (arg.type_ == detail::type::none_type)
return arg;
arg.value_ = values_[id];
return arg;
}
template <typename Char>
format_arg get(basic_string_view<Char> name) const {
int id = get_id(name);
return id >= 0 ? get(id) : format_arg();
}
template <typename Char>
int get_id(basic_string_view<Char> name) const {
if (!has_named_args())
return -1;
const auto& named_args =
(is_packed() ? values_[-1] : args_[-1].value_).named_args;
for (size_t i = 0; i < named_args.size; ++i) {
if (named_args.data[i].name == name)
return named_args.data[i].id;
}
return -1;
}
int max_size() const {
unsigned long long max_packed = detail::max_packed_args;
return static_cast<int>(is_packed() ? max_packed
: desc_ & ~detail::is_unpacked_bit);
}
};
// # 1941 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
struct format_args : basic_format_args<format_context> {
template <typename... Args>
inline __attribute__((always_inline)) format_args(const Args&... args)
: basic_format_args(args...) {
}
};
struct wformat_args : basic_format_args<wformat_context> {
using basic_format_args::basic_format_args;
};
namespace detail {
template <typename Char,
enable_if_t<(!std::is_same<Char, char>::value), int> = 0>
std::basic_string<Char> vformat(
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args);
std::string vformat(string_view format_str, format_args args);
template <typename Char>
void vformat_to(buffer<Char>& buf,
basic_string_view<Char> format_str,
basic_format_args<basic_format_context<
detail::buffer_appender<type_identity_t<Char>>,
type_identity_t<Char>>> args,
detail::locale_ref loc = {});
template <typename Char,
typename Args,
enable_if_t<(!std::is_same<Char, char>::value), int> = 0>
inline void vprint_mojibake(std::FILE*, basic_string_view<Char>, const Args&) {
}
void vprint_mojibake(std::FILE*, string_view, format_args);
inline void vprint_mojibake(std::FILE*, string_view, format_args) {
}
} // namespace detail
template <typename OutputIt,
typename S,
typename Char = char_t<S>,
bool enable = detail::is_output_iterator<OutputIt, Char>::value>
auto vformat_to(OutputIt out,
const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args)
-> typename std::enable_if<enable, OutputIt>::type {
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
detail::vformat_to(buf, to_string_view(format_str), args);
return detail::get_iterator(buf);
}
// # 2000 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename OutputIt,
typename S,
typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
inline auto format_to(OutputIt out, const S& format_str, Args&&... args) ->
typename std::enable_if<enable, OutputIt>::type {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return vformat_to(out, to_string_view(format_str), vargs);
}
template <typename OutputIt>
struct format_to_n_result {
OutputIt out;
size_t size;
};
template <typename OutputIt,
typename Char,
typename... Args,
enable_if_t<(detail::is_output_iterator<OutputIt, Char>::value),
int> = 0>
inline format_to_n_result<OutputIt> vformat_to_n(
OutputIt out,
size_t n,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(
out, n);
detail::vformat_to(buf, format_str, args);
return {buf.out(), buf.count()};
}
// # 2033 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename OutputIt,
typename S,
typename... Args,
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
inline auto format_to_n(OutputIt out,
size_t n,
const S& format_str,
const Args&... args) ->
typename std::enable_if<enable, format_to_n_result<OutputIt>>::type {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return vformat_to_n(out, n, to_string_view(format_str), vargs);
}
template <typename... Args>
inline size_t formatted_size(string_view format_str, Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
detail::counting_buffer<> buf;
detail::vformat_to(buf, format_str, vargs);
return buf.count();
}
template <typename S, typename Char = char_t<S>>
inline __attribute__((always_inline)) std::basic_string<Char> vformat(
const S& format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
return detail::vformat(to_string_view(format_str), args);
}
// # 2073 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename S, typename... Args, typename Char = char_t<S>>
inline __attribute__((always_inline)) std::basic_string<Char> format(
const S& format_str, Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::vformat(to_string_view(format_str), vargs);
}
void vprint(string_view, format_args);
void vprint(std::FILE*, string_view, format_args);
// # 2093 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename S, typename... Args, typename Char = char_t<S>>
inline void print(std::FILE* f, const S& format_str, Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::is_unicode<Char>()
? vprint(f, to_string_view(format_str), vargs)
: detail::vprint_mojibake(
f, to_string_view(format_str), vargs);
}
// # 2112 "tlm/deps/fmt.exploded/include/fmt/core.h" 3 4
template <typename S, typename... Args, typename Char = char_t<S>>
inline void print(const S& format_str, Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
return detail::is_unicode<Char>()
? vprint(to_string_view(format_str), vargs)
: detail::vprint_mojibake(
stdout, to_string_view(format_str), vargs);
}
} // namespace v7
} // namespace fmt
// # 26 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/fmt.h"
// 2 # 1 "tlm/deps/fmt.exploded/include/fmt/format.h" 1 3 4 # 36
// "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4 # 37
// "tlm/deps/fmt.exploded/include/fmt/format.h" 2 3 4 # 38
// "tlm/deps/fmt.exploded/include/fmt/format.h" 2 3 4 # 39
// "tlm/deps/fmt.exploded/include/fmt/format.h" 2 3 4
// # 1 "tlm/deps/fmt.exploded/include/fmt/core.h" 1 3 4
// # 45 "tlm/deps/fmt.exploded/include/fmt/format.h" 2 3 4
// # 275 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
namespace fmt {
inline namespace v7 {
namespace detail {
template <typename Dest, typename Source>
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source), "size mismatch");
Dest dest;
std::memcpy(&dest, &source, sizeof(dest));
return dest;
}
inline bool is_big_endian() {
const auto u = 1u;
struct bytes {
char data[sizeof(u)];
};
return bit_cast<bytes>(u).data[0] == 0;
}
struct fallback_uintptr {
unsigned char value[sizeof(void*)];
fallback_uintptr() = default;
explicit fallback_uintptr(const void* p) {
*this = bit_cast<fallback_uintptr>(p);
if (is_big_endian()) {
for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
std::swap(value[i], value[j]);
}
}
};
using uintptr_t = ::uintptr_t;
inline uintptr_t to_uintptr(const void* p) {
return bit_cast<uintptr_t>(p);
}
// # 322 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename T>
constexpr T max_value() {
return (std::numeric_limits<T>::max)();
}
template <typename T>
constexpr int num_bits() {
return std::numeric_limits<T>::digits;
}
template <>
constexpr int num_bits<int128_t>() {
return 128;
}
template <>
constexpr int num_bits<uint128_t>() {
return 128;
}
template <>
constexpr int num_bits<fallback_uintptr>() {
return static_cast<int>(sizeof(void*) *
std::numeric_limits<unsigned char>::digits);
}
inline __attribute__((always_inline)) void assume(bool condition) {
(void)condition;
}
template <typename T>
using iterator_t = decltype(std::begin(std::declval<T&>()));
template <typename T>
using sentinel_t = decltype(std::end(std::declval<T&>()));
template <typename Char>
inline Char* get_data(std::basic_string<Char>& s) {
return &s[0];
}
template <typename Container>
inline typename Container::value_type* get_data(Container& c) {
return c.data();
}
// # 364 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename T>
using checked_ptr = T*;
template <typename T>
inline T* make_checked(T* p, size_t) {
return p;
}
template <typename Container,
enable_if_t<(is_contiguous<Container>::value), int> = 0>
inline checked_ptr<typename Container::value_type> reserve(
std::back_insert_iterator<Container> it, size_t n) {
Container& c = get_container(it);
size_t size = c.size();
c.resize(size + n);
return make_checked(get_data(c) + size, n);
}
template <typename T>
inline buffer_appender<T> reserve(buffer_appender<T> it, size_t n) {
buffer<T>& buf = get_container(it);
buf.try_reserve(buf.size() + n);
return it;
}
template <typename Iterator>
inline Iterator& reserve(Iterator& it, size_t) {
return it;
}
template <typename T, typename OutputIt>
constexpr T* to_pointer(OutputIt, size_t) {
return nullptr;
}
template <typename T>
T* to_pointer(buffer_appender<T> it, size_t n) {
buffer<T>& buf = get_container(it);
auto size = buf.size();
if (buf.capacity() < size + n)
return nullptr;
buf.try_resize(size + n);
return buf.data() + size;
}
template <typename Container,
enable_if_t<(is_contiguous<Container>::value), int> = 0>
inline std::back_insert_iterator<Container> base_iterator(
std::back_insert_iterator<Container>& it,
checked_ptr<typename Container::value_type>) {
return it;
}
template <typename Iterator>
inline Iterator base_iterator(Iterator, Iterator it) {
return it;
}
class counting_iterator {
private:
size_t count_;
public:
using iterator_category = std::output_iterator_tag;
using difference_type = std::ptrdiff_t;
using pointer = void;
using reference = void;
using _Unchecked_type = counting_iterator;
struct value_type {
template <typename T>
void operator=(const T&) {
}
};
counting_iterator() : count_(0) {
}
size_t count() const {
return count_;
}
counting_iterator& operator++() {
++count_;
return *this;
}
counting_iterator operator++(int) {
auto it = *this;
++*this;
return it;
}
friend counting_iterator operator+(counting_iterator it,
difference_type n) {
it.count_ += static_cast<size_t>(n);
return it;
}
value_type operator*() const {
return {};
}
};
template <typename OutputIt>
class truncating_iterator_base {
protected:
OutputIt out_;
size_t limit_;
size_t count_;
truncating_iterator_base(OutputIt out, size_t limit)
: out_(out), limit_(limit), count_(0) {
}
public:
using iterator_category = std::output_iterator_tag;
using value_type = typename std::iterator_traits<OutputIt>::value_type;
using difference_type = void;
using pointer = void;
using reference = void;
using _Unchecked_type = truncating_iterator_base;
OutputIt base() const {
return out_;
}
size_t count() const {
return count_;
}
};
template <typename OutputIt,
typename Enable = typename std::is_void<
typename std::iterator_traits<OutputIt>::value_type>::type>
class truncating_iterator;
template <typename OutputIt>
class truncating_iterator<OutputIt, std::false_type>
: public truncating_iterator_base<OutputIt> {
mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_;
public:
using value_type = typename truncating_iterator_base<OutputIt>::value_type;
truncating_iterator(OutputIt out, size_t limit)
: truncating_iterator_base<OutputIt>(out, limit) {
}
truncating_iterator& operator++() {
if (this->count_++ < this->limit_)
++this->out_;
return *this;
}
truncating_iterator operator++(int) {
auto it = *this;
++*this;
return it;
}
value_type& operator*() const {
return this->count_ < this->limit_ ? *this->out_ : blackhole_;
}
};
template <typename OutputIt>
class truncating_iterator<OutputIt, std::true_type>
: public truncating_iterator_base<OutputIt> {
public:
truncating_iterator(OutputIt out, size_t limit)
: truncating_iterator_base<OutputIt>(out, limit) {
}
template <typename T>
truncating_iterator& operator=(T val) {
if (this->count_++ < this->limit_)
*this->out_++ = val;
return *this;
}
truncating_iterator& operator++() {
return *this;
}
truncating_iterator& operator++(int) {
return *this;
}
truncating_iterator& operator*() {
return *this;
}
};
template <typename Char>
inline size_t count_code_points(basic_string_view<Char> s) {
return s.size();
}
inline size_t count_code_points(basic_string_view<char> s) {
const char* data = s.data();
size_t num_code_points = 0;
for (size_t i = 0, size = s.size(); i != size; ++i) {
if ((data[i] & 0xc0) != 0x80)
++num_code_points;
}
return num_code_points;
}
inline size_t count_code_points(basic_string_view<char8_type> s) {
return count_code_points(basic_string_view<char>(
reinterpret_cast<const char*>(s.data()), s.size()));
}
template <typename Char>
inline size_t code_point_index(basic_string_view<Char> s, size_t n) {
size_t size = s.size();
return n < size ? n : size;
}
inline size_t code_point_index(basic_string_view<char8_type> s, size_t n) {
const char8_type* data = s.data();
size_t num_code_points = 0;
for (size_t i = 0, size = s.size(); i != size; ++i) {
if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) {
return i;
}
}
return s.size();
}
template <typename InputIt, typename OutChar>
using needs_conversion = bool_constant<
std::is_same<typename std::iterator_traits<InputIt>::value_type,
char>::value &&
std::is_same<OutChar, char8_type>::value>;
template <typename OutChar,
typename InputIt,
typename OutputIt,
enable_if_t<(!needs_conversion<InputIt, OutChar>::value), int> = 0>
OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
return std::copy(begin, end, it);
}
template <typename OutChar,
typename InputIt,
typename OutputIt,
enable_if_t<(needs_conversion<InputIt, OutChar>::value), int> = 0>
OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
return std::transform(
begin, end, it, [](char c) { return static_cast<char8_type>(c); });
}
template <typename Char, typename InputIt>
inline counting_iterator copy_str(InputIt begin,
InputIt end,
counting_iterator it) {
return it + (end - begin);
}
template <typename T>
using is_fast_float = bool_constant<std::numeric_limits<T>::is_iec559 &&
sizeof(T) <= sizeof(double)>;
template <typename T>
template <typename U>
void buffer<T>::append(const U* begin, const U* end) {
do {
auto count = to_unsigned(end - begin);
try_reserve(size_ + count);
auto free_cap = capacity_ - size_;
if (free_cap < count)
count = free_cap;
std::uninitialized_copy_n(
begin, count, make_checked(ptr_ + size_, count));
size_ += count;
begin += count;
} while (begin != end);
}
template <typename OutputIt, typename T, typename Traits>
void iterator_buffer<OutputIt, T, Traits>::flush() {
out_ = std::copy_n(data_, this->limit(this->size()), out_);
this->clear();
}
} // namespace detail
enum { inline_buffer_size = 500 };
// # 652 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename T,
size_t SIZE = inline_buffer_size,
typename Allocator = std::allocator<T>>
class basic_memory_buffer final : public detail::buffer<T> {
private:
T store_[SIZE];
Allocator alloc_;
void deallocate() {
T* data = this->data();
if (data != store_)
alloc_.deallocate(data, this->capacity());
}
protected:
void grow(size_t size) final override;
public:
using value_type = T;
using const_reference = const T&;
explicit basic_memory_buffer(const Allocator& alloc = Allocator())
: alloc_(alloc) {
this->set(store_, SIZE);
}
~basic_memory_buffer() {
deallocate();
}
private:
void move(basic_memory_buffer& other) {
alloc_ = std::move(other.alloc_);
T* data = other.data();
size_t size = other.size(), capacity = other.capacity();
if (data == other.store_) {
this->set(store_, capacity);
std::uninitialized_copy(other.store_,
other.store_ + size,
detail::make_checked(store_, capacity));
} else {
this->set(data, capacity);
other.set(other.store_, 0);
}
this->resize(size);
}
public:
basic_memory_buffer(basic_memory_buffer&& other) noexcept {
move(other);
}
basic_memory_buffer& operator=(basic_memory_buffer&& other) noexcept {
((this != &other)
? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
714,
("")));
deallocate();
move(other);
return *this;
}
Allocator get_allocator() const {
return alloc_;
}
void resize(size_t count) {
this->try_resize(count);
}
void reserve(size_t new_capacity) {
this->try_reserve(new_capacity);
}
using detail::buffer<T>::append;
template <typename ContiguousRange>
void append(const ContiguousRange& range) {
append(range.data(), range.data() + range.size());
}
};
template <typename T, size_t SIZE, typename Allocator>
void basic_memory_buffer<T, SIZE, Allocator>::grow(size_t size) {
size_t old_capacity = this->capacity();
size_t new_capacity = old_capacity + old_capacity / 2;
if (size > new_capacity)
new_capacity = size;
T* old_data = this->data();
T* new_data =
std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
std::uninitialized_copy(old_data,
old_data + this->size(),
detail::make_checked(new_data, new_capacity));
this->set(new_data, new_capacity);
if (old_data != store_)
alloc_.deallocate(old_data, old_capacity);
}
using memory_buffer = basic_memory_buffer<char>;
using wmemory_buffer = basic_memory_buffer<wchar_t>;
template <typename T, size_t SIZE, typename Allocator>
struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
};
class format_error : public std::runtime_error {
public:
explicit format_error(const char* message) : std::runtime_error(message) {
}
explicit format_error(const std::string& message)
: std::runtime_error(message) {
}
format_error(const format_error&) = default;
format_error& operator=(const format_error&) = default;
format_error(format_error&&) = default;
format_error& operator=(format_error&&) = default;
~format_error() noexcept override;
};
namespace detail {
template <typename T>
using is_signed =
std::integral_constant<bool,
std::numeric_limits<T>::is_signed ||
std::is_same<T, int128_t>::value>;
template <typename T, enable_if_t<(is_signed<T>::value), int> = 0>
constexpr bool is_negative(T value) {
return value < 0;
}
template <typename T, enable_if_t<(!is_signed<T>::value), int> = 0>
constexpr bool is_negative(T) {
return false;
}
template <typename T, enable_if_t<(std::is_floating_point<T>::value), int> = 0>
constexpr bool is_supported_floating_point(T) {
return (std::is_same<T, float>::value && 1) ||
(std::is_same<T, double>::value && 1) ||
(std::is_same<T, long double>::value && 1);
}
template <typename T>
using uint32_or_64_or_128_t =
conditional_t<num_bits<T>() <= 32 && !0,
uint32_t,
conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
struct uint128_wrapper {
uint128_wrapper() = default;
uint128_t internal_;
uint128_wrapper(uint64_t high, uint64_t low) noexcept
: internal_{static_cast<uint128_t>(low) |
(static_cast<uint128_t>(high) << 64)} {
}
uint128_wrapper(uint128_t u) : internal_{u} {
}
uint64_t high() const noexcept {
return uint64_t(internal_ >> 64);
}
uint64_t low() const noexcept {
return uint64_t(internal_);
}
uint128_wrapper& operator+=(uint64_t n) noexcept {
internal_ += n;
return *this;
}
// # 858 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
};
template <typename T>
struct divtest_table_entry {
T mod_inv;
T max_quotient;
};
template <typename T = void>
struct basic_data {
static const uint64_t powers_of_10_64[];
static const uint32_t zero_or_powers_of_10_32_new[];
static const uint64_t zero_or_powers_of_10_64_new[];
static const uint64_t grisu_pow10_significands[];
static const int16_t grisu_pow10_exponents[];
static const divtest_table_entry<uint32_t> divtest_table_for_pow5_32[];
static const divtest_table_entry<uint64_t> divtest_table_for_pow5_64[];
static const uint64_t dragonbox_pow10_significands_64[];
static const uint128_wrapper dragonbox_pow10_significands_128[];
static const uint64_t log10_2_significand = 0x4d104d427de7fbcc;
static const uint64_t powers_of_5_64[];
static const uint32_t dragonbox_pow10_recovery_errors[];
using digit_pair = char[2];
static const digit_pair digits[];
static const char hex_digits[];
static const char foreground_color[];
static const char background_color[];
static const char reset_color[5];
static const wchar_t wreset_color[5];
static const char signs[];
static const char left_padding_shifts[5];
static const char right_padding_shifts[5];
static const uint32_t zero_or_powers_of_10_32[];
static const uint64_t zero_or_powers_of_10_64[];
};
inline __attribute__((always_inline)) uint16_t bsr2log10(int bsr) {
static constexpr uint16_t data[] = {
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
return data[bsr];
}
extern template struct basic_data<void>;
struct data : basic_data<> {};
inline int count_digits(uint64_t n) {
auto t = bsr2log10(__builtin_clzll(n | 1) ^ 63);
return t - (n < data::zero_or_powers_of_10_64_new[t]);
}
// # 945 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
inline int count_digits(uint128_t n) {
int count = 1;
for (;;) {
if (n < 10)
return count;
if (n < 100)
return count + 1;
if (n < 1000)
return count + 2;
if (n < 10000)
return count + 3;
n /= 10000U;
count += 4;
}
}
template <unsigned BITS, typename UInt>
inline int count_digits(UInt n) {
int num_digits = 0;
do {
++num_digits;
} while ((n >>= BITS) != 0);
return num_digits;
}
template <>
int count_digits<4>(detail::fallback_uintptr n);
// # 989 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
inline int count_digits(uint32_t n) {
auto t = bsr2log10(__builtin_clz(n | 1) ^ 31);
return t - (n < data::zero_or_powers_of_10_32_new[t]);
}
template <typename Int>
constexpr int digits10() noexcept {
return std::numeric_limits<Int>::digits10;
}
template <>
constexpr int digits10<int128_t>() noexcept {
return 38;
}
template <>
constexpr int digits10<uint128_t>() noexcept {
return 38;
}
template <typename Char>
std::string grouping_impl(locale_ref loc);
template <typename Char>
inline std::string grouping(locale_ref loc) {
return grouping_impl<char>(loc);
}
template <>
inline std::string grouping<wchar_t>(locale_ref loc) {
return grouping_impl<wchar_t>(loc);
}
template <typename Char>
Char thousands_sep_impl(locale_ref loc);
template <typename Char>
inline Char thousands_sep(locale_ref loc) {
return Char(thousands_sep_impl<char>(loc));
}
template <>
inline wchar_t thousands_sep(locale_ref loc) {
return thousands_sep_impl<wchar_t>(loc);
}
template <typename Char>
Char decimal_point_impl(locale_ref loc);
template <typename Char>
inline Char decimal_point(locale_ref loc) {
return Char(decimal_point_impl<char>(loc));
}
template <>
inline wchar_t decimal_point(locale_ref loc) {
return decimal_point_impl<wchar_t>(loc);
}
template <typename Char>
bool equal2(const Char* lhs, const char* rhs) {
return lhs[0] == rhs[0] && lhs[1] == rhs[1];
}
inline bool equal2(const char* lhs, const char* rhs) {
return memcmp(lhs, rhs, 2) == 0;
}
template <typename Char>
void copy2(Char* dst, const char* src) {
*dst++ = static_cast<Char>(*src++);
*dst = static_cast<Char>(*src);
}
inline __attribute__((always_inline)) void copy2(char* dst, const char* src) {
memcpy(dst, src, 2);
}
template <typename Iterator>
struct format_decimal_result {
Iterator begin;
Iterator end;
};
template <typename Char, typename UInt>
inline format_decimal_result<Char*> format_decimal(Char* out,
UInt value,
int size) {
((size >= count_digits(value))
? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
1051,
("invalid digit count")));
out += size;
Char* end = out;
while (value >= 100) {
out -= 2;
copy2(out, data::digits[value % 100]);
value /= 100;
}
if (value < 10) {
*--out = static_cast<Char>('0' + value);
return {out, end};
}
out -= 2;
copy2(out, data::digits[value]);
return {out, end};
}
template <typename Char,
typename UInt,
typename Iterator,
enable_if_t<(!std::is_pointer<remove_cvref_t<Iterator>>::value),
int> = 0>
inline format_decimal_result<Iterator> format_decimal(Iterator out,
UInt value,
int size) {
Char buffer[digits10<UInt>() + 1];
auto end = format_decimal(buffer, value, size).end;
return {out, detail::copy_str<Char>(buffer, end, out)};
}
template <unsigned BASE_BITS, typename Char, typename UInt>
inline Char* format_uint(Char* buffer,
UInt value,
int num_digits,
bool upper = false) {
buffer += num_digits;
Char* end = buffer;
do {
const char* digits = upper ? "0123456789ABCDEF" : data::hex_digits;
unsigned digit = (value & ((1 << BASE_BITS) - 1));
*--buffer = static_cast<Char>(
BASE_BITS < 4 ? static_cast<char>('0' + digit) : digits[digit]);
} while ((value >>= BASE_BITS) != 0);
return end;
}
template <unsigned BASE_BITS, typename Char>
Char* format_uint(Char* buffer,
detail::fallback_uintptr n,
int num_digits,
bool = false) {
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
int start = (num_digits + char_digits - 1) / char_digits - 1;
if (int start_digits = num_digits % char_digits) {
unsigned value = n.value[start--];
buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
}
for (; start >= 0; --start) {
unsigned value = n.value[start];
buffer += char_digits;
auto p = buffer;
for (int i = 0; i < char_digits; ++i) {
unsigned digit = (value & ((1 << BASE_BITS) - 1));
*--p = static_cast<Char>(data::hex_digits[digit]);
value >>= BASE_BITS;
}
}
return buffer;
}
template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
format_uint<BASE_BITS>(ptr, value, num_digits, upper);
return out;
}
char buffer[num_bits<UInt>() / BASE_BITS + 1];
format_uint<BASE_BITS>(buffer, value, num_digits, upper);
return detail::copy_str<Char>(buffer, buffer + num_digits, out);
}
class utf8_to_utf16 {
private:
wmemory_buffer buffer_;
public:
explicit utf8_to_utf16(string_view s);
operator wstring_view() const {
return {&buffer_[0], size()};
}
size_t size() const {
return buffer_.size() - 1;
}
const wchar_t* c_str() const {
return &buffer_[0];
}
std::wstring str() const {
return {&buffer_[0], size()};
}
};
template <typename T = void>
struct null {};
template <typename Char>
struct fill_t {
private:
enum { max_size = 4 };
Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
unsigned char size_ = 1;
public:
constexpr void operator=(basic_string_view<Char> s) {
auto size = s.size();
if (size > max_size) {
throw format_error("invalid fill");
return;
}
for (size_t i = 0; i < size; ++i)
data_[i] = s[i];
size_ = static_cast<unsigned char>(size);
}
size_t size() const {
return size_;
}
const Char* data() const {
return data_;
}
constexpr Char& operator[](size_t index) {
return data_[index];
}
constexpr const Char& operator[](size_t index) const {
return data_[index];
}
};
} // namespace detail
namespace align {
enum type { none, left, right, center, numeric };
}
using align_t = align::type;
namespace sign {
enum type { none, minus, plus, space };
}
using sign_t = sign::type;
template <typename Char>
struct basic_format_specs {
int width;
int precision;
char type;
align_t align : 4;
sign_t sign : 3;
bool alt : 1;
detail::fill_t<Char> fill;
constexpr basic_format_specs()
: width(0),
precision(-1),
type(0),
align(align::none),
sign(sign::none),
alt(false) {
}
};
using format_specs = basic_format_specs<char>;
namespace detail {
namespace dragonbox {
template <class T>
struct float_info;
template <>
struct float_info<float> {
using carrier_uint = uint32_t;
static const int significand_bits = 23;
static const int exponent_bits = 8;
static const int min_exponent = -126;
static const int max_exponent = 127;
static const int exponent_bias = -127;
static const int decimal_digits = 9;
static const int kappa = 1;
static const int big_divisor = 100;
static const int small_divisor = 10;
static const int min_k = -31;
static const int max_k = 46;
static const int cache_bits = 64;
static const int divisibility_check_by_5_threshold = 39;
static const int case_fc_pm_half_lower_threshold = -1;
static const int case_fc_pm_half_upper_threshold = 6;
static const int case_fc_lower_threshold = -2;
static const int case_fc_upper_threshold = 6;
static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
static const int shorter_interval_tie_lower_threshold = -35;
static const int shorter_interval_tie_upper_threshold = -35;
static const int max_trailing_zeros = 7;
};
template <>
struct float_info<double> {
using carrier_uint = uint64_t;
static const int significand_bits = 52;
static const int exponent_bits = 11;
static const int min_exponent = -1022;
static const int max_exponent = 1023;
static const int exponent_bias = -1023;
static const int decimal_digits = 17;
static const int kappa = 2;
static const int big_divisor = 1000;
static const int small_divisor = 100;
static const int min_k = -292;
static const int max_k = 326;
static const int cache_bits = 128;
static const int divisibility_check_by_5_threshold = 86;
static const int case_fc_pm_half_lower_threshold = -2;
static const int case_fc_pm_half_upper_threshold = 9;
static const int case_fc_lower_threshold = -4;
static const int case_fc_upper_threshold = 9;
static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
static const int shorter_interval_tie_lower_threshold = -77;
static const int shorter_interval_tie_upper_threshold = -77;
static const int max_trailing_zeros = 16;
};
template <typename T>
struct decimal_fp {
using significand_type = typename float_info<T>::carrier_uint;
significand_type significand;
int exponent;
};
template <typename T>
decimal_fp<T> to_decimal(T x) noexcept;
} // namespace dragonbox
template <typename T>
constexpr typename dragonbox::float_info<T>::carrier_uint exponent_mask() {
using uint = typename dragonbox::float_info<T>::carrier_uint;
return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
<< dragonbox::float_info<T>::significand_bits;
}
enum class float_format : unsigned char { general, exp, fixed, hex };
struct float_specs {
int precision;
float_format format : 8;
sign_t sign : 8;
bool upper : 1;
bool locale : 1;
bool binary32 : 1;
bool use_grisu : 1;
bool showpoint : 1;
};
template <typename Char, typename It>
It write_exponent(int exp, It it) {
((-10000 < exp && exp < 10000)
? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
1300,
("exponent out of range")));
if (exp < 0) {
*it++ = static_cast<Char>('-');
exp = -exp;
} else {
*it++ = static_cast<Char>('+');
}
if (exp >= 100) {
const char* top = data::digits[exp / 100];
if (exp >= 1000)
*it++ = static_cast<Char>(top[0]);
*it++ = static_cast<Char>(top[1]);
exp %= 100;
}
const char* d = data::digits[exp];
*it++ = static_cast<Char>(d[0]);
*it++ = static_cast<Char>(d[1]);
return it;
}
template <typename T>
int format_float(T value, int precision, float_specs specs, buffer<char>& buf);
template <typename T>
int snprintf_float(T value,
int precision,
float_specs specs,
buffer<char>& buf);
template <typename T>
T promote_float(T value) {
return value;
}
inline double promote_float(float value) {
return static_cast<double>(value);
}
template <typename Handler>
constexpr void handle_int_type_spec(char spec, Handler&& handler) {
switch (spec) {
case 0:
case 'd':
handler.on_dec();
break;
case 'x':
case 'X':
handler.on_hex();
break;
case 'b':
case 'B':
handler.on_bin();
break;
case 'o':
handler.on_oct();
break;
case 'L':
handler.on_num();
break;
case 'c':
handler.on_chr();
break;
default:
handler.on_error();
}
}
template <typename ErrorHandler = error_handler, typename Char>
constexpr float_specs parse_float_type_spec(
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
auto result = float_specs();
result.showpoint = specs.alt;
switch (specs.type) {
case 0:
result.format = float_format::general;
result.showpoint |= specs.precision > 0;
break;
case 'G':
result.upper = true;
[[fallthrough]];
case 'g':
result.format = float_format::general;
break;
case 'E':
result.upper = true;
[[fallthrough]];
case 'e':
result.format = float_format::exp;
result.showpoint |= specs.precision != 0;
break;
case 'F':
result.upper = true;
[[fallthrough]];
case 'f':
result.format = float_format::fixed;
result.showpoint |= specs.precision != 0;
break;
case 'A':
result.upper = true;
[[fallthrough]];
case 'a':
result.format = float_format::hex;
break;
case 'L':
result.locale = true;
break;
default:
eh.on_error("invalid type specifier");
break;
}
return result;
}
template <typename Char, typename Handler>
constexpr void handle_char_specs(const basic_format_specs<Char>* specs,
Handler&& handler) {
if (!specs)
return handler.on_char();
if (specs->type && specs->type != 'c')
return handler.on_int();
if (specs->align == align::numeric || specs->sign != sign::none ||
specs->alt)
handler.on_error("invalid format specifier for char");
handler.on_char();
}
template <typename Char, typename Handler>
constexpr void handle_cstring_type_spec(Char spec, Handler&& handler) {
if (spec == 0 || spec == 's')
handler.on_string();
else if (spec == 'p')
handler.on_pointer();
else
handler.on_error("invalid type specifier");
}
template <typename Char, typename ErrorHandler>
constexpr void check_string_type_spec(Char spec, ErrorHandler&& eh) {
if (spec != 0 && spec != 's')
eh.on_error("invalid type specifier");
}
template <typename Char, typename ErrorHandler>
constexpr void check_pointer_type_spec(Char spec, ErrorHandler&& eh) {
if (spec != 0 && spec != 'p')
eh.on_error("invalid type specifier");
}
template <typename ErrorHandler>
class int_type_checker : private ErrorHandler {
public:
constexpr explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {
}
constexpr void on_dec() {
}
constexpr void on_hex() {
}
constexpr void on_bin() {
}
constexpr void on_oct() {
}
constexpr void on_num() {
}
constexpr void on_chr() {
}
constexpr void on_error() {
ErrorHandler::on_error("invalid type specifier");
}
};
template <typename ErrorHandler>
class char_specs_checker : public ErrorHandler {
private:
char type_;
public:
constexpr char_specs_checker(char type, ErrorHandler eh)
: ErrorHandler(eh), type_(type) {
}
constexpr void on_int() {
handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
}
constexpr void on_char() {
}
};
template <typename ErrorHandler>
class cstring_type_checker : public ErrorHandler {
public:
constexpr explicit cstring_type_checker(ErrorHandler eh)
: ErrorHandler(eh) {
}
constexpr void on_string() {
}
constexpr void on_pointer() {
}
};
template <typename OutputIt, typename Char>
__attribute__((noinline)) OutputIt fill(OutputIt it,
size_t n,
const fill_t<Char>& fill) {
auto fill_size = fill.size();
if (fill_size == 1)
return std::fill_n(it, n, fill[0]);
for (size_t i = 0; i < n; ++i)
it = std::copy_n(fill.data(), fill_size, it);
return it;
}
template <align::type align = align::left,
typename OutputIt,
typename Char,
typename F>
inline OutputIt write_padded(OutputIt out,
const basic_format_specs<Char>& specs,
size_t size,
size_t width,
F&& f) {
static_assert(align == align::left || align == align::right, "");
unsigned spec_width = to_unsigned(specs.width);
size_t padding = spec_width > width ? spec_width - width : 0;
auto* shifts = align == align::left ? data::left_padding_shifts
: data::right_padding_shifts;
size_t left_padding = padding >> shifts[specs.align];
auto it = reserve(out, size + padding * specs.fill.size());
it = fill(it, left_padding, specs.fill);
it = f(it);
it = fill(it, padding - left_padding, specs.fill);
return base_iterator(out, it);
}
template <align::type align = align::left,
typename OutputIt,
typename Char,
typename F>
inline OutputIt write_padded(OutputIt out,
const basic_format_specs<Char>& specs,
size_t size,
F&& f) {
return write_padded<align>(out, specs, size, size, f);
}
template <typename Char, typename OutputIt>
OutputIt write_bytes(OutputIt out,
string_view bytes,
const basic_format_specs<Char>& specs) {
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
const char* data = bytes.data();
return copy_str<Char>(data, data + bytes.size(), it);
});
}
template <typename Char>
struct write_int_data {
size_t size;
size_t padding;
write_int_data(int num_digits,
string_view prefix,
const basic_format_specs<Char>& specs)
: size(prefix.size() + to_unsigned(num_digits)), padding(0) {
if (specs.align == align::numeric) {
auto width = to_unsigned(specs.width);
if (width > size) {
padding = width - size;
size = width;
}
} else if (specs.precision > num_digits) {
size = prefix.size() + to_unsigned(specs.precision);
padding = to_unsigned(specs.precision - num_digits);
}
}
};
template <typename OutputIt, typename Char, typename F>
OutputIt write_int(OutputIt out,
int num_digits,
string_view prefix,
const basic_format_specs<Char>& specs,
F f) {
auto data = write_int_data<Char>(num_digits, prefix, specs);
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
if (prefix.size() != 0)
it = copy_str<Char>(prefix.begin(), prefix.end(), it);
it = std::fill_n(it, data.padding, static_cast<Char>('0'));
return f(it);
});
}
template <typename StrChar, typename Char, typename OutputIt>
OutputIt write(OutputIt out,
basic_string_view<StrChar> s,
const basic_format_specs<Char>& specs) {
auto data = s.data();
auto size = s.size();
if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
size = code_point_index(s, to_unsigned(specs.precision));
auto width =
specs.width != 0
? count_code_points(basic_string_view<StrChar>(data, size))
: 0;
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
return write_padded(out, specs, size, width, [=](iterator it) {
return copy_str<Char>(data, data + size, it);
});
}
template <typename OutputIt, typename Char, typename UInt>
struct int_writer {
OutputIt out;
locale_ref locale;
const basic_format_specs<Char>& specs;
UInt abs_value;
char prefix[4];
unsigned prefix_size;
using iterator =
remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
string_view get_prefix() const {
return string_view(prefix, prefix_size);
}
template <typename Int>
int_writer(OutputIt output,
locale_ref loc,
Int value,
const basic_format_specs<Char>& s)
: out(output),
locale(loc),
specs(s),
abs_value(static_cast<UInt>(value)),
prefix_size(0) {
static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value,
"");
if (is_negative(value)) {
prefix[0] = '-';
++prefix_size;
abs_value = 0 - abs_value;
} else if (specs.sign != sign::none && specs.sign != sign::minus) {
prefix[0] = specs.sign == sign::plus ? '+' : ' ';
++prefix_size;
}
}
void on_dec() {
auto num_digits = count_digits(abs_value);
out = write_int(
out,
num_digits,
get_prefix(),
specs,
[this, num_digits](iterator it) {
return format_decimal<Char>(it, abs_value, num_digits).end;
});
}
void on_hex() {
if (specs.alt) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = specs.type;
}
int num_digits = count_digits<4>(abs_value);
out = write_int(
out,
num_digits,
get_prefix(),
specs,
[this, num_digits](iterator it) {
return format_uint<4, Char>(
it, abs_value, num_digits, specs.type != 'x');
});
}
void on_bin() {
if (specs.alt) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = static_cast<char>(specs.type);
}
int num_digits = count_digits<1>(abs_value);
out = write_int(out,
num_digits,
get_prefix(),
specs,
[this, num_digits](iterator it) {
return format_uint<1, Char>(
it, abs_value, num_digits);
});
}
void on_oct() {
int num_digits = count_digits<3>(abs_value);
if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
prefix[prefix_size++] = '0';
}
out = write_int(out,
num_digits,
get_prefix(),
specs,
[this, num_digits](iterator it) {
return format_uint<3, Char>(
it, abs_value, num_digits);
});
}
enum { sep_size = 1 };
void on_num() {
std::string groups = grouping<Char>(locale);
if (groups.empty())
return on_dec();
auto sep = thousands_sep<Char>(locale);
if (!sep)
return on_dec();
int num_digits = count_digits(abs_value);
int size = num_digits, n = num_digits;
std::string::const_iterator group = groups.cbegin();
while (group != groups.cend() && n > *group && *group > 0 &&
*group != max_value<char>()) {
size += sep_size;
n -= *group;
++group;
}
if (group == groups.cend())
size += sep_size * ((n - 1) / groups.back());
char digits[40];
format_decimal(digits, abs_value, num_digits);
basic_memory_buffer<Char> buffer;
size += static_cast<int>(prefix_size);
const auto usize = to_unsigned(size);
buffer.resize(usize);
basic_string_view<Char> s(&sep, sep_size);
int digit_index = 0;
group = groups.cbegin();
auto p = buffer.data() + size - 1;
for (int i = num_digits - 1; i > 0; --i) {
*p-- = static_cast<Char>(digits[i]);
if (*group <= 0 || ++digit_index % *group != 0 ||
*group == max_value<char>())
continue;
if (group + 1 != groups.cend()) {
digit_index = 0;
++group;
}
std::uninitialized_copy(
s.data(), s.data() + s.size(), make_checked(p, s.size()));
p -= s.size();
}
*p-- = static_cast<Char>(*digits);
if (prefix_size != 0)
*p = static_cast<Char>('-');
auto data = buffer.data();
out = write_padded<align::right>(
out, specs, usize, usize, [=](iterator it) {
return copy_str<Char>(data, data + size, it);
});
}
void on_chr() {
*out++ = static_cast<Char>(abs_value);
}
[[noreturn]] void on_error() {
throw format_error("invalid type specifier");
}
};
template <typename Char, typename OutputIt>
OutputIt write_nonfinite(OutputIt out,
bool isinf,
const basic_format_specs<Char>& specs,
const float_specs& fspecs) {
auto str = isinf ? (fspecs.upper ? "INF" : "inf")
: (fspecs.upper ? "NAN" : "nan");
constexpr size_t str_size = 3;
auto sign = fspecs.sign;
auto size = str_size + (sign ? 1 : 0);
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
return write_padded(out, specs, size, [=](iterator it) {
if (sign)
*it++ = static_cast<Char>(data::signs[sign]);
return copy_str<Char>(str, str + str_size, it);
});
}
struct big_decimal_fp {
const char* significand;
int significand_size;
int exponent;
};
inline int get_significand_size(const big_decimal_fp& fp) {
return fp.significand_size;
}
template <typename T>
inline int get_significand_size(const dragonbox::decimal_fp<T>& fp) {
return count_digits(fp.significand);
}
template <typename Char, typename OutputIt>
inline OutputIt write_significand(OutputIt out,
const char* significand,
int& significand_size) {
return copy_str<Char>(significand, significand + significand_size, out);
}
template <typename Char, typename OutputIt, typename UInt>
inline OutputIt write_significand(OutputIt out,
UInt significand,
int significand_size) {
return format_decimal<Char>(out, significand, significand_size).end;
}
template <typename Char,
typename UInt,
enable_if_t<(std::is_integral<UInt>::value), int> = 0>
inline Char* write_significand(Char* out,
UInt significand,
int significand_size,
int integral_size,
Char decimal_point) {
if (!decimal_point)
return format_decimal(out, significand, significand_size).end;
auto end = format_decimal(out + 1, significand, significand_size).end;
if (integral_size == 1)
out[0] = out[1];
else
std::copy_n(out + 1, integral_size, out);
out[integral_size] = decimal_point;
return end;
}
template <typename OutputIt,
typename UInt,
typename Char,
enable_if_t<(!std::is_pointer<remove_cvref_t<OutputIt>>::value),
int> = 0>
inline OutputIt write_significand(OutputIt out,
UInt significand,
int significand_size,
int integral_size,
Char decimal_point) {
Char buffer[digits10<UInt>() + 2];
auto end = write_significand(buffer,
significand,
significand_size,
integral_size,
decimal_point);
return detail::copy_str<Char>(buffer, end, out);
}
template <typename OutputIt, typename Char>
inline OutputIt write_significand(OutputIt out,
const char* significand,
int significand_size,
int integral_size,
Char decimal_point) {
out = detail::copy_str<Char>(significand, significand + integral_size, out);
if (!decimal_point)
return out;
*out++ = decimal_point;
return detail::copy_str<Char>(
significand + integral_size, significand + significand_size, out);
}
template <typename OutputIt, typename DecimalFP, typename Char>
OutputIt write_float(OutputIt out,
const DecimalFP& fp,
const basic_format_specs<Char>& specs,
float_specs fspecs,
Char decimal_point) {
auto significand = fp.significand;
int significand_size = get_significand_size(fp);
static const Char zero = static_cast<Char>('0');
auto sign = fspecs.sign;
size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
int output_exp = fp.exponent + significand_size - 1;
auto use_exp_format = [=]() {
if (fspecs.format == float_format::exp)
return true;
if (fspecs.format != float_format::general)
return false;
const int exp_lower = -4, exp_upper = 16;
return output_exp < exp_lower ||
output_exp >=
(fspecs.precision > 0 ? fspecs.precision : exp_upper);
};
if (use_exp_format()) {
int num_zeros = 0;
if (fspecs.showpoint) {
num_zeros = (std::max)(fspecs.precision - significand_size, 0);
size += to_unsigned(num_zeros);
} else if (significand_size == 1) {
decimal_point = Char();
}
auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
int exp_digits = 2;
if (abs_output_exp >= 100)
exp_digits = abs_output_exp >= 1000 ? 4 : 3;
size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
char exp_char = fspecs.upper ? 'E' : 'e';
auto write = [=](iterator it) {
if (sign)
*it++ = static_cast<Char>(data::signs[sign]);
it = write_significand(
it, significand, significand_size, 1, decimal_point);
if (num_zeros > 0)
it = std::fill_n(it, num_zeros, zero);
*it++ = static_cast<Char>(exp_char);
return write_exponent<Char>(output_exp, it);
};
return specs.width > 0
? write_padded<align::right>(out, specs, size, write)
: base_iterator(out, write(reserve(out, size)));
}
int exp = fp.exponent + significand_size;
if (fp.exponent >= 0) {
size += to_unsigned(fp.exponent);
int num_zeros = fspecs.precision - exp;
if (fspecs.showpoint) {
if (num_zeros <= 0 && fspecs.format != float_format::fixed)
num_zeros = 1;
if (num_zeros > 0)
size += to_unsigned(num_zeros);
}
return write_padded<align::right>(out, specs, size, [&](iterator it) {
if (sign)
*it++ = static_cast<Char>(data::signs[sign]);
it = write_significand<Char>(it, significand, significand_size);
it = std::fill_n(it, fp.exponent, zero);
if (!fspecs.showpoint)
return it;
*it++ = decimal_point;
return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
});
} else if (exp > 0) {
int num_zeros =
fspecs.showpoint ? fspecs.precision - significand_size : 0;
size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
return write_padded<align::right>(out, specs, size, [&](iterator it) {
if (sign)
*it++ = static_cast<Char>(data::signs[sign]);
it = write_significand(
it, significand, significand_size, exp, decimal_point);
return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
});
}
int num_zeros = -exp;
if (significand_size == 0 && fspecs.precision >= 0 &&
fspecs.precision < num_zeros) {
num_zeros = fspecs.precision;
}
size += 2 + to_unsigned(num_zeros);
return write_padded<align::right>(out, specs, size, [&](iterator it) {
if (sign)
*it++ = static_cast<Char>(data::signs[sign]);
*it++ = zero;
if (num_zeros == 0 && significand_size == 0 && !fspecs.showpoint)
return it;
*it++ = decimal_point;
it = std::fill_n(it, num_zeros, zero);
return write_significand<Char>(it, significand, significand_size);
});
}
template <typename Char,
typename OutputIt,
typename T,
enable_if_t<(std::is_floating_point<T>::value), int> = 0>
OutputIt write(OutputIt out,
T value,
basic_format_specs<Char> specs,
locale_ref loc = {}) {
if (const_check(!is_supported_floating_point(value)))
return out;
float_specs fspecs = parse_float_type_spec(specs);
fspecs.sign = specs.sign;
if (std::signbit(value)) {
fspecs.sign = sign::minus;
value = -value;
} else if (fspecs.sign == sign::minus) {
fspecs.sign = sign::none;
}
if (!std::isfinite(value))
return write_nonfinite(out, std::isinf(value), specs, fspecs);
if (specs.align == align::numeric && fspecs.sign) {
auto it = reserve(out, 1);
*it++ = static_cast<Char>(data::signs[fspecs.sign]);
out = base_iterator(out, it);
fspecs.sign = sign::none;
if (specs.width != 0)
--specs.width;
}
memory_buffer buffer;
if (fspecs.format == float_format::hex) {
if (fspecs.sign)
buffer.push_back(data::signs[fspecs.sign]);
snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
return write_bytes(out, {buffer.data(), buffer.size()}, specs);
}
int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
if (fspecs.format == float_format::exp) {
if (precision == max_value<int>())
throw format_error("number is too big");
else
++precision;
}
if (const_check(std::is_same<T, float>()))
fspecs.binary32 = true;
fspecs.use_grisu = is_fast_float<T>();
int exp = format_float(promote_float(value), precision, fspecs, buffer);
fspecs.precision = precision;
Char point =
fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>('.');
auto fp =
big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
return write_float(out, fp, specs, fspecs, point);
}
template <typename Char,
typename OutputIt,
typename T,
enable_if_t<(is_fast_float<T>::value), int> = 0>
OutputIt write(OutputIt out, T value) {
if (const_check(!is_supported_floating_point(value)))
return out;
using floaty =
conditional_t<std::is_same<T, long double>::value, double, T>;
using uint = typename dragonbox::float_info<floaty>::carrier_uint;
auto bits = bit_cast<uint>(value);
auto fspecs = float_specs();
auto sign_bit = bits & (uint(1) << (num_bits<uint>() - 1));
if (sign_bit != 0) {
fspecs.sign = sign::minus;
value = -value;
}
static const auto specs = basic_format_specs<Char>();
uint mask = exponent_mask<floaty>();
if ((bits & mask) == mask)
return write_nonfinite(out, std::isinf(value), specs, fspecs);
auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
return write_float(out, dec, specs, fspecs, static_cast<Char>('.'));
}
template <typename Char,
typename OutputIt,
typename T,
enable_if_t<(std::is_floating_point<T>::value &&
!is_fast_float<T>::value),
int> = 0>
inline OutputIt write(OutputIt out, T value) {
return write(out, value, basic_format_specs<Char>());
}
template <typename Char, typename OutputIt>
OutputIt write_char(OutputIt out,
Char value,
const basic_format_specs<Char>& specs) {
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
return write_padded(out, specs, 1, [=](iterator it) {
*it++ = value;
return it;
});
}
template <typename Char, typename OutputIt, typename UIntPtr>
OutputIt write_ptr(OutputIt out,
UIntPtr value,
const basic_format_specs<Char>* specs) {
int num_digits = count_digits<4>(value);
auto size = to_unsigned(num_digits) + size_t(2);
using iterator = remove_reference_t<decltype(reserve(out, 0))>;
auto write = [=](iterator it) {
*it++ = static_cast<Char>('0');
*it++ = static_cast<Char>('x');
return format_uint<4, Char>(it, value, num_digits);
};
return specs ? write_padded<align::right>(out, *specs, size, write)
: base_iterator(out, write(reserve(out, size)));
}
template <typename T>
struct is_integral : std::is_integral<T> {};
template <>
struct is_integral<int128_t> : std::true_type {};
template <>
struct is_integral<uint128_t> : std::true_type {};
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, monostate) {
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2007,
("")));
return out;
}
template <typename Char,
typename OutputIt,
enable_if_t<(!std::is_same<Char, char>::value), int> = 0>
OutputIt write(OutputIt out, string_view value) {
auto it = reserve(out, value.size());
it = copy_str<Char>(value.begin(), value.end(), it);
return base_iterator(out, it);
}
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, basic_string_view<Char> value) {
auto it = reserve(out, value.size());
it = std::copy(value.begin(), value.end(), it);
return base_iterator(out, it);
}
template <typename Char>
buffer_appender<Char> write(buffer_appender<Char> out,
basic_string_view<Char> value) {
get_container(out).append(value.begin(), value.end());
return out;
}
template <typename Char,
typename OutputIt,
typename T,
enable_if_t<(is_integral<T>::value && !std::is_same<T, bool>::value &&
!std::is_same<T, Char>::value),
int> = 0
>
OutputIt write(OutputIt out, T value) {
auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
bool negative = is_negative(value);
if (negative)
abs_value = ~abs_value + 1;
int num_digits = count_digits(abs_value);
auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
auto it = reserve(out, size);
if (auto ptr = to_pointer<Char>(it, size)) {
if (negative)
*ptr++ = static_cast<Char>('-');
format_decimal<Char>(ptr, abs_value, num_digits);
return out;
}
if (negative)
*it++ = static_cast<Char>('-');
it = format_decimal<Char>(it, abs_value, num_digits).end;
return base_iterator(out, it);
}
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, bool value) {
return write<Char>(out, string_view(value ? "true" : "false"));
}
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, Char value) {
auto it = reserve(out, 1);
*it++ = value;
return base_iterator(out, it);
}
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, const Char* value) {
if (!value) {
throw format_error("string pointer is null");
} else {
auto length = std::char_traits<Char>::length(value);
out = write(out, basic_string_view<Char>(value, length));
}
return out;
}
template <typename Char, typename OutputIt>
OutputIt write(OutputIt out, const void* value) {
return write_ptr<Char>(out, to_uintptr(value), nullptr);
}
template <typename Char, typename OutputIt, typename T>
auto write(OutputIt out, const T& value) -> typename std::enable_if<
mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value ==
type::custom_type,
OutputIt>::type {
using context_type = basic_format_context<OutputIt, Char>;
using formatter_type =
conditional_t<has_formatter<T, context_type>::value,
typename context_type::template formatter_type<T>,
fallback_formatter<T, Char>>;
context_type ctx(out, {}, {});
return formatter_type().format(value, ctx);
}
template <typename OutputIt, typename Char>
struct default_arg_formatter {
using context = basic_format_context<OutputIt, Char>;
OutputIt out;
basic_format_args<context> args;
locale_ref loc;
template <typename T>
OutputIt operator()(T value) {
return write<Char>(out, value);
}
OutputIt operator()(typename basic_format_arg<context>::handle handle) {
basic_format_parse_context<Char> parse_ctx({});
basic_format_context<OutputIt, Char> format_ctx(out, args, loc);
handle.format(parse_ctx, format_ctx);
return format_ctx.out();
}
};
template <typename OutputIt,
typename Char,
typename ErrorHandler = error_handler>
class arg_formatter_base {
public:
using iterator = OutputIt;
using char_type = Char;
using format_specs = basic_format_specs<Char>;
private:
iterator out_;
locale_ref locale_;
format_specs* specs_;
auto reserve(size_t n) -> decltype(detail::reserve(out_, n)) {
return detail::reserve(out_, n);
}
using reserve_iterator = remove_reference_t<decltype(
detail::reserve(std::declval<iterator&>(), 0))>;
template <typename T>
void write_int(T value, const format_specs& spec) {
using uint_type = uint32_or_64_or_128_t<T>;
int_writer<iterator, Char, uint_type> w(out_, locale_, value, spec);
handle_int_type_spec(spec.type, w);
out_ = w.out;
}
void write(char value) {
auto&& it = reserve(1);
*it++ = value;
}
template <typename Ch,
enable_if_t<(std::is_same<Ch, Char>::value), int> = 0>
void write(Ch value) {
out_ = detail::write<Char>(out_, value);
}
void write(string_view value) {
auto&& it = reserve(value.size());
it = copy_str<Char>(value.begin(), value.end(), it);
}
void write(wstring_view value) {
static_assert(std::is_same<Char, wchar_t>::value, "");
auto&& it = reserve(value.size());
it = std::copy(value.begin(), value.end(), it);
}
template <typename Ch>
void write(const Ch* s, size_t size, const format_specs& specs) {
auto width = specs.width != 0
? count_code_points(basic_string_view<Ch>(s, size))
: 0;
out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) {
return copy_str<Char>(s, s + size, it);
});
}
template <typename Ch>
void write(basic_string_view<Ch> s, const format_specs& specs = {}) {
out_ = detail::write(out_, s, specs);
}
void write_pointer(const void* p) {
out_ = write_ptr<char_type>(out_, to_uintptr(p), specs_);
}
struct char_spec_handler : ErrorHandler {
arg_formatter_base& formatter;
Char value;
char_spec_handler(arg_formatter_base& f, Char val)
: formatter(f), value(val) {
}
void on_int() {
formatter.write_int(static_cast<int>(value), *formatter.specs_);
}
void on_char() {
if (formatter.specs_)
formatter.out_ =
write_char(formatter.out_, value, *formatter.specs_);
else
formatter.write(value);
}
};
struct cstring_spec_handler : error_handler {
arg_formatter_base& formatter;
const Char* value;
cstring_spec_handler(arg_formatter_base& f, const Char* val)
: formatter(f), value(val) {
}
void on_string() {
formatter.write(value);
}
void on_pointer() {
formatter.write_pointer(value);
}
};
protected:
iterator out() {
return out_;
}
format_specs* specs() {
return specs_;
}
void write(bool value) {
if (specs_)
write(string_view(value ? "true" : "false"), *specs_);
else
out_ = detail::write<Char>(out_, value);
}
void write(const Char* value) {
if (!value) {
throw format_error("string pointer is null");
} else {
auto length = std::char_traits<char_type>::length(value);
basic_string_view<char_type> sv(value, length);
specs_ ? write(sv, *specs_) : write(sv);
}
}
public:
arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc)
: out_(out), locale_(loc), specs_(s) {
}
iterator operator()(monostate) {
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2242,
("invalid argument type")));
return out_;
}
template <typename T, enable_if_t<(is_integral<T>::value), int> = 0>
inline __attribute__((always_inline)) iterator operator()(T value) {
if (specs_)
write_int(value, *specs_);
else
out_ = detail::write<Char>(out_, value);
return out_;
}
iterator operator()(Char value) {
handle_char_specs(specs_,
char_spec_handler(*this, static_cast<Char>(value)));
return out_;
}
iterator operator()(bool value) {
if (specs_ && specs_->type)
return (*this)(value ? 1 : 0);
write(value != 0);
return out_;
}
template <typename T,
enable_if_t<(std::is_floating_point<T>::value), int> = 0>
iterator operator()(T value) {
auto specs = specs_ ? *specs_ : format_specs();
if (const_check(is_supported_floating_point(value)))
out_ = detail::write(out_, value, specs, locale_);
else
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2273,
("unsupported float argument type")));
return out_;
}
iterator operator()(const Char* value) {
if (!specs_)
return write(value), out_;
handle_cstring_type_spec(specs_->type,
cstring_spec_handler(*this, value));
return out_;
}
iterator operator()(basic_string_view<Char> value) {
if (specs_) {
check_string_type_spec(specs_->type, error_handler());
write(value, *specs_);
} else {
write(value);
}
return out_;
}
iterator operator()(const void* value) {
if (specs_)
check_pointer_type_spec(specs_->type, error_handler());
write_pointer(value);
return out_;
}
};
template <typename OutputIt, typename Char>
class arg_formatter : public arg_formatter_base<OutputIt, Char> {
private:
using char_type = Char;
using base = arg_formatter_base<OutputIt, Char>;
using context_type = basic_format_context<OutputIt, Char>;
context_type& ctx_;
basic_format_parse_context<char_type>* parse_ctx_;
const Char* ptr_;
public:
using iterator = typename base::iterator;
using format_specs = typename base::format_specs;
// # 2323 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
explicit arg_formatter(
context_type& ctx,
basic_format_parse_context<char_type>* parse_ctx = nullptr,
format_specs* specs = nullptr,
const Char* ptr = nullptr)
: base(ctx.out(), specs, ctx.locale()),
ctx_(ctx),
parse_ctx_(parse_ctx),
ptr_(ptr) {
}
using base::operator();
iterator operator()(
typename basic_format_arg<context_type>::handle handle) {
if (ptr_)
advance_to(*parse_ctx_, ptr_);
handle.format(*parse_ctx_, ctx_);
return ctx_.out();
}
};
template <typename Char>
constexpr bool is_name_start(Char c) {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
}
template <typename Char, typename ErrorHandler>
constexpr int parse_nonnegative_int(const Char*& begin,
const Char* end,
ErrorHandler&& eh) {
((begin != end && '0' <= *begin && *begin <= '9')
? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2351,
("")));
unsigned value = 0;
constexpr unsigned max_int = max_value<int>();
unsigned big = max_int / 10;
do {
if (value > big) {
value = max_int + 1;
break;
}
value = value * 10 + unsigned(*begin - '0');
++begin;
} while (begin != end && '0' <= *begin && *begin <= '9');
if (value > max_int)
eh.on_error("number is too big");
return static_cast<int>(value);
}
template <typename Context>
class custom_formatter {
private:
using char_type = typename Context::char_type;
basic_format_parse_context<char_type>& parse_ctx_;
Context& ctx_;
public:
explicit custom_formatter(basic_format_parse_context<char_type>& parse_ctx,
Context& ctx)
: parse_ctx_(parse_ctx), ctx_(ctx) {
}
void operator()(typename basic_format_arg<Context>::handle h) const {
h.format(parse_ctx_, ctx_);
}
template <typename T>
void operator()(T) const {
}
};
template <typename T>
using is_integer =
bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
!std::is_same<T, char>::value &&
!std::is_same<T, wchar_t>::value>;
template <typename ErrorHandler>
class width_checker {
public:
explicit constexpr width_checker(ErrorHandler& eh) : handler_(eh) {
}
template <typename T, enable_if_t<(is_integer<T>::value), int> = 0>
constexpr unsigned long long operator()(T value) {
if (is_negative(value))
handler_.on_error("negative width");
return static_cast<unsigned long long>(value);
}
template <typename T, enable_if_t<(!is_integer<T>::value), int> = 0>
constexpr unsigned long long operator()(T) {
handler_.on_error("width is not integer");
return 0;
}
private:
ErrorHandler& handler_;
};
template <typename ErrorHandler>
class precision_checker {
public:
explicit constexpr precision_checker(ErrorHandler& eh) : handler_(eh) {
}
template <typename T, enable_if_t<(is_integer<T>::value), int> = 0>
constexpr unsigned long long operator()(T value) {
if (is_negative(value))
handler_.on_error("negative precision");
return static_cast<unsigned long long>(value);
}
template <typename T, enable_if_t<(!is_integer<T>::value), int> = 0>
constexpr unsigned long long operator()(T) {
handler_.on_error("precision is not integer");
return 0;
}
private:
ErrorHandler& handler_;
};
template <typename Char>
class specs_setter {
public:
explicit constexpr specs_setter(basic_format_specs<Char>& specs)
: specs_(specs) {
}
constexpr specs_setter(const specs_setter& other) : specs_(other.specs_) {
}
constexpr void on_align(align_t align) {
specs_.align = align;
}
constexpr void on_fill(basic_string_view<Char> fill) {
specs_.fill = fill;
}
constexpr void on_plus() {
specs_.sign = sign::plus;
}
constexpr void on_minus() {
specs_.sign = sign::minus;
}
constexpr void on_space() {
specs_.sign = sign::space;
}
constexpr void on_hash() {
specs_.alt = true;
}
constexpr void on_zero() {
specs_.align = align::numeric;
specs_.fill[0] = Char('0');
}
constexpr void on_width(int width) {
specs_.width = width;
}
constexpr void on_precision(int precision) {
specs_.precision = precision;
}
constexpr void end_precision() {
}
constexpr void on_type(Char type) {
specs_.type = static_cast<char>(type);
}
protected:
basic_format_specs<Char>& specs_;
};
template <typename ErrorHandler>
class numeric_specs_checker {
public:
constexpr numeric_specs_checker(ErrorHandler& eh, detail::type arg_type)
: error_handler_(eh), arg_type_(arg_type) {
}
constexpr void require_numeric_argument() {
if (!is_arithmetic_type(arg_type_))
error_handler_.on_error(
"format specifier requires numeric argument");
}
constexpr void check_sign() {
require_numeric_argument();
if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
error_handler_.on_error(
"format specifier requires signed argument");
}
}
constexpr void check_precision() {
if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)
error_handler_.on_error(
"precision not allowed for this argument type");
}
private:
ErrorHandler& error_handler_;
detail::type arg_type_;
};
template <typename Handler>
class specs_checker : public Handler {
private:
numeric_specs_checker<Handler> checker_;
constexpr Handler& error_handler() {
return *this;
}
public:
constexpr specs_checker(const Handler& handler, detail::type arg_type)
: Handler(handler), checker_(error_handler(), arg_type) {
}
constexpr specs_checker(const specs_checker& other)
: Handler(other), checker_(error_handler(), other.arg_type_) {
}
constexpr void on_align(align_t align) {
if (align == align::numeric)
checker_.require_numeric_argument();
Handler::on_align(align);
}
constexpr void on_plus() {
checker_.check_sign();
Handler::on_plus();
}
constexpr void on_minus() {
checker_.check_sign();
Handler::on_minus();
}
constexpr void on_space() {
checker_.check_sign();
Handler::on_space();
}
constexpr void on_hash() {
checker_.require_numeric_argument();
Handler::on_hash();
}
constexpr void on_zero() {
checker_.require_numeric_argument();
Handler::on_zero();
}
constexpr void end_precision() {
checker_.check_precision();
}
};
template <template <typename> class Handler,
typename FormatArg,
typename ErrorHandler>
constexpr int get_dynamic_spec(FormatArg arg, ErrorHandler eh) {
unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
if (value > to_unsigned(max_value<int>()))
eh.on_error("number is too big");
return static_cast<int>(value);
}
struct auto_id {};
template <typename Context, typename ID>
constexpr typename Context::format_arg get_arg(Context& ctx, ID id) {
auto arg = ctx.arg(id);
if (!arg)
ctx.on_error("argument not found");
return arg;
}
template <typename ParseContext, typename Context>
class specs_handler : public specs_setter<typename Context::char_type> {
public:
using char_type = typename Context::char_type;
constexpr specs_handler(basic_format_specs<char_type>& specs,
ParseContext& parse_ctx,
Context& ctx)
: specs_setter<char_type>(specs),
parse_context_(parse_ctx),
context_(ctx) {
}
template <typename Id>
constexpr void on_dynamic_width(Id arg_id) {
this->specs_.width = get_dynamic_spec<width_checker>(
get_arg(arg_id), context_.error_handler());
}
template <typename Id>
constexpr void on_dynamic_precision(Id arg_id) {
this->specs_.precision = get_dynamic_spec<precision_checker>(
get_arg(arg_id), context_.error_handler());
}
void on_error(const char* message) {
context_.on_error(message);
}
private:
using format_arg = typename Context::format_arg;
constexpr format_arg get_arg(auto_id) {
return detail::get_arg(context_, parse_context_.next_arg_id());
}
constexpr format_arg get_arg(int arg_id) {
parse_context_.check_arg_id(arg_id);
return detail::get_arg(context_, arg_id);
}
constexpr format_arg get_arg(basic_string_view<char_type> arg_id) {
parse_context_.check_arg_id(arg_id);
return detail::get_arg(context_, arg_id);
}
ParseContext& parse_context_;
Context& context_;
};
enum class arg_id_kind { none, index, name };
template <typename Char>
struct arg_ref {
constexpr arg_ref() : kind(arg_id_kind::none), val() {
}
constexpr explicit arg_ref(int index)
: kind(arg_id_kind::index), val(index) {
}
constexpr explicit arg_ref(basic_string_view<Char> name)
: kind(arg_id_kind::name), val(name) {
}
constexpr arg_ref& operator=(int idx) {
kind = arg_id_kind::index;
val.index = idx;
return *this;
}
arg_id_kind kind;
union value {
constexpr value(int id = 0) : index{id} {
}
constexpr value(basic_string_view<Char> n) : name(n) {
}
int index;
basic_string_view<Char> name;
} val;
};
template <typename Char>
struct dynamic_format_specs : basic_format_specs<Char> {
arg_ref<Char> width_ref;
arg_ref<Char> precision_ref;
};
template <typename ParseContext>
class dynamic_specs_handler
: public specs_setter<typename ParseContext::char_type> {
public:
using char_type = typename ParseContext::char_type;
constexpr dynamic_specs_handler(dynamic_format_specs<char_type>& specs,
ParseContext& ctx)
: specs_setter<char_type>(specs), specs_(specs), context_(ctx) {
}
constexpr dynamic_specs_handler(const dynamic_specs_handler& other)
: specs_setter<char_type>(other),
specs_(other.specs_),
context_(other.context_) {
}
template <typename Id>
constexpr void on_dynamic_width(Id arg_id) {
specs_.width_ref = make_arg_ref(arg_id);
}
template <typename Id>
constexpr void on_dynamic_precision(Id arg_id) {
specs_.precision_ref = make_arg_ref(arg_id);
}
constexpr void on_error(const char* message) {
context_.on_error(message);
}
private:
using arg_ref_type = arg_ref<char_type>;
constexpr arg_ref_type make_arg_ref(int arg_id) {
context_.check_arg_id(arg_id);
return arg_ref_type(arg_id);
}
constexpr arg_ref_type make_arg_ref(auto_id) {
return arg_ref_type(context_.next_arg_id());
}
constexpr arg_ref_type make_arg_ref(basic_string_view<char_type> arg_id) {
context_.check_arg_id(arg_id);
basic_string_view<char_type> format_str(
context_.begin(),
to_unsigned(context_.end() - context_.begin()));
return arg_ref_type(arg_id);
}
dynamic_format_specs<char_type>& specs_;
ParseContext& context_;
};
template <typename Char, typename IDHandler>
constexpr const Char* parse_arg_id(const Char* begin,
const Char* end,
IDHandler&& handler) {
((begin != end) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2702,
("")));
Char c = *begin;
if (c == '}' || c == ':') {
handler();
return begin;
}
if (c >= '0' && c <= '9') {
int index = 0;
if (c != '0')
index = parse_nonnegative_int(begin, end, handler);
else
++begin;
if (begin == end || (*begin != '}' && *begin != ':'))
handler.on_error("invalid format string");
else
handler(index);
return begin;
}
if (!is_name_start(c)) {
handler.on_error("invalid format string");
return begin;
}
auto it = begin;
do {
++it;
} while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9')));
handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));
return it;
}
template <typename SpecHandler, typename Char>
struct width_adapter {
explicit constexpr width_adapter(SpecHandler& h) : handler(h) {
}
constexpr void operator()() {
handler.on_dynamic_width(auto_id());
}
constexpr void operator()(int id) {
handler.on_dynamic_width(id);
}
constexpr void operator()(basic_string_view<Char> id) {
handler.on_dynamic_width(id);
}
constexpr void on_error(const char* message) {
handler.on_error(message);
}
SpecHandler& handler;
};
template <typename SpecHandler, typename Char>
struct precision_adapter {
explicit constexpr precision_adapter(SpecHandler& h) : handler(h) {
}
constexpr void operator()() {
handler.on_dynamic_precision(auto_id());
}
constexpr void operator()(int id) {
handler.on_dynamic_precision(id);
}
constexpr void operator()(basic_string_view<Char> id) {
handler.on_dynamic_precision(id);
}
constexpr void on_error(const char* message) {
handler.on_error(message);
}
SpecHandler& handler;
};
template <typename Char>
constexpr int code_point_length(const Char* begin) {
if (const_check(sizeof(Char) != 1))
return 1;
constexpr char lengths[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0};
int len = lengths[static_cast<unsigned char>(*begin) >> 3];
return len + !len;
}
template <typename Char>
constexpr bool is_ascii_letter(Char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
template <typename Char, enable_if_t<(std::is_integral<Char>::value), int> = 0>
constexpr Char to_ascii(Char value) {
return value;
}
template <typename Char, enable_if_t<(std::is_enum<Char>::value), int> = 0>
constexpr typename std::underlying_type<Char>::type to_ascii(Char value) {
return value;
}
template <typename Char, typename Handler>
constexpr const Char* parse_align(const Char* begin,
const Char* end,
Handler&& handler) {
((begin != end) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2797,
("")));
auto align = align::none;
auto p = begin + code_point_length(begin);
if (p >= end)
p = begin;
for (;;) {
switch (to_ascii(*p)) {
case '<':
align = align::left;
break;
case '>':
align = align::right;
break;
case '^':
align = align::center;
break;
}
if (align != align::none) {
if (p != begin) {
auto c = *begin;
if (c == '{')
return handler.on_error("invalid fill character '{'"),
begin;
handler.on_fill(
basic_string_view<Char>(begin, to_unsigned(p - begin)));
begin = p + 1;
} else
++begin;
handler.on_align(align);
break;
} else if (p == begin) {
break;
}
p = begin;
}
return begin;
}
template <typename Char, typename Handler>
constexpr const Char* parse_width(const Char* begin,
const Char* end,
Handler&& handler) {
((begin != end) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
2840,
("")));
if ('0' <= *begin && *begin <= '9') {
handler.on_width(parse_nonnegative_int(begin, end, handler));
} else if (*begin == '{') {
++begin;
if (begin != end)
begin = parse_arg_id(
begin, end, width_adapter<Handler, Char>(handler));
if (begin == end || *begin != '}')
return handler.on_error("invalid format string"), begin;
++begin;
}
return begin;
}
template <typename Char, typename Handler>
constexpr const Char* parse_precision(const Char* begin,
const Char* end,
Handler&& handler) {
++begin;
auto c = begin != end ? *begin : Char();
if ('0' <= c && c <= '9') {
handler.on_precision(parse_nonnegative_int(begin, end, handler));
} else if (c == '{') {
++begin;
if (begin != end) {
begin = parse_arg_id(
begin, end, precision_adapter<Handler, Char>(handler));
}
if (begin == end || *begin++ != '}')
return handler.on_error("invalid format string"), begin;
} else {
return handler.on_error("missing precision specifier"), begin;
}
handler.end_precision();
return begin;
}
template <typename Char, typename SpecHandler>
constexpr const Char* parse_format_specs(const Char* begin,
const Char* end,
SpecHandler&& handler) {
if (begin == end)
return begin;
begin = parse_align(begin, end, handler);
if (begin == end)
return begin;
switch (to_ascii(*begin)) {
case '+':
handler.on_plus();
++begin;
break;
case '-':
handler.on_minus();
++begin;
break;
case ' ':
handler.on_space();
++begin;
break;
}
if (begin == end)
return begin;
if (*begin == '#') {
handler.on_hash();
if (++begin == end)
return begin;
}
if (*begin == '0') {
handler.on_zero();
if (++begin == end)
return begin;
}
begin = parse_width(begin, end, handler);
if (begin == end)
return begin;
if (*begin == '.') {
begin = parse_precision(begin, end, handler);
}
if (begin != end && *begin != '}')
handler.on_type(*begin++);
return begin;
}
template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
constexpr bool find(Ptr first, Ptr last, T value, Ptr& out) {
for (out = first; out != last; ++out) {
if (*out == value)
return true;
}
return false;
}
template <>
inline bool find<false, char>(const char* first,
const char* last,
char value,
const char*& out) {
out = static_cast<const char*>(
std::memchr(first, value, detail::to_unsigned(last - first)));
return out != nullptr;
}
template <typename Handler, typename Char>
struct id_adapter {
Handler& handler;
int arg_id;
constexpr void operator()() {
arg_id = handler.on_arg_id();
}
constexpr void operator()(int id) {
arg_id = handler.on_arg_id(id);
}
constexpr void operator()(basic_string_view<Char> id) {
arg_id = handler.on_arg_id(id);
}
constexpr void on_error(const char* message) {
handler.on_error(message);
}
};
template <typename Char, typename Handler>
constexpr const Char* parse_replacement_field(const Char* begin,
const Char* end,
Handler&& handler) {
++begin;
if (begin == end)
return handler.on_error("invalid format string"), end;
if (*begin == '}') {
handler.on_replacement_field(handler.on_arg_id(), begin);
} else if (*begin == '{') {
handler.on_text(begin, begin + 1);
} else {
auto adapter = id_adapter<Handler, Char>{handler, 0};
begin = parse_arg_id(begin, end, adapter);
Char c = begin != end ? *begin : Char();
if (c == '}') {
handler.on_replacement_field(adapter.arg_id, begin);
} else if (c == ':') {
begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
if (begin == end || *begin != '}')
return handler.on_error("unknown format specifier"), end;
} else {
return handler.on_error("missing '}' in format string"), end;
}
}
return begin + 1;
}
template <bool IS_CONSTEXPR, typename Char, typename Handler>
constexpr inline __attribute__((always_inline)) void parse_format_string(
basic_string_view<Char> format_str, Handler&& handler) {
auto begin = format_str.data();
auto end = begin + format_str.size();
if (end - begin < 32) {
const Char* p = begin;
while (p != end) {
auto c = *p++;
if (c == '{') {
handler.on_text(begin, p - 1);
begin = p = parse_replacement_field(p - 1, end, handler);
} else if (c == '}') {
if (p == end || *p != '}')
return handler.on_error("unmatched '}' in format string");
handler.on_text(begin, p);
begin = ++p;
}
}
handler.on_text(begin, end);
return;
}
struct writer {
constexpr void operator()(const Char* pbegin, const Char* pend) {
if (pbegin == pend)
return;
for (;;) {
const Char* p = nullptr;
if (!find<IS_CONSTEXPR>(pbegin, pend, '}', p))
return handler_.on_text(pbegin, pend);
++p;
if (p == pend || *p != '}')
return handler_.on_error("unmatched '}' in format string");
handler_.on_text(pbegin, p);
pbegin = p + 1;
}
}
Handler& handler_;
} write{handler};
while (begin != end) {
const Char* p = begin;
if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, '{', p))
return write(begin, end);
write(begin, p);
begin = parse_replacement_field(p, end, handler);
}
}
template <typename T, typename ParseContext>
constexpr const typename ParseContext::char_type* parse_format_specs(
ParseContext& ctx) {
using char_type = typename ParseContext::char_type;
using context = buffer_context<char_type>;
using mapped_type =
conditional_t<detail::mapped_type_constant<T, context>::value !=
type::custom_type,
decltype(
arg_mapper<context>().map(std::declval<T>())),
T>;
auto f = conditional_t<has_formatter<mapped_type, context>::value,
formatter<mapped_type, char_type>,
detail::fallback_formatter<T, char_type>>();
return f.parse(ctx);
}
template <typename OutputIt, typename Char, typename Context>
struct format_handler : detail::error_handler {
basic_format_parse_context<Char> parse_context;
Context context;
format_handler(OutputIt out,
basic_string_view<Char> str,
basic_format_args<Context> format_args,
detail::locale_ref loc)
: parse_context(str), context(out, format_args, loc) {
}
void on_text(const Char* begin, const Char* end) {
auto size = to_unsigned(end - begin);
auto out = context.out();
auto&& it = reserve(out, size);
it = std::copy_n(begin, size, it);
context.advance_to(out);
}
int on_arg_id() {
return parse_context.next_arg_id();
}
int on_arg_id(int id) {
return parse_context.check_arg_id(id), id;
}
int on_arg_id(basic_string_view<Char> id) {
int arg_id = context.arg_id(id);
if (arg_id < 0)
on_error("argument not found");
return arg_id;
}
inline __attribute__((always_inline)) void on_replacement_field(
int id, const Char*) {
auto arg = get_arg(context, id);
context.advance_to(visit_format_arg(
default_arg_formatter<OutputIt, Char>{
context.out(), context.args(), context.locale()},
arg));
}
const Char* on_format_specs(int id, const Char* begin, const Char* end) {
auto arg = get_arg(context, id);
if (arg.type() == type::custom_type) {
advance_to(parse_context, begin);
visit_format_arg(custom_formatter<Context>(parse_context, context),
arg);
return parse_context.begin();
}
auto specs = basic_format_specs<Char>();
if (begin + 1 < end && begin[1] == '}' && is_ascii_letter(*begin)) {
specs.type = static_cast<char>(*begin++);
} else {
using parse_context_t = basic_format_parse_context<Char>;
specs_checker<specs_handler<parse_context_t, Context>> handler(
specs_handler<parse_context_t, Context>(
specs, parse_context, context),
arg.type());
begin = parse_format_specs(begin, end, handler);
if (begin == end || *begin != '}')
on_error("missing '}' in format string");
}
context.advance_to(visit_format_arg(
arg_formatter<OutputIt, Char>(context, &parse_context, &specs),
arg));
return begin;
}
};
template <typename Char, typename ErrorHandler = error_handler>
class compile_parse_context
: public basic_format_parse_context<Char, ErrorHandler> {
private:
int num_args_;
using base = basic_format_parse_context<Char, ErrorHandler>;
public:
explicit constexpr compile_parse_context(basic_string_view<Char> format_str,
int num_args = max_value<int>(),
ErrorHandler eh = {})
: base(format_str, eh), num_args_(num_args) {
}
constexpr int next_arg_id() {
int id = base::next_arg_id();
if (id >= num_args_)
this->on_error("argument not found");
return id;
}
constexpr void check_arg_id(int id) {
base::check_arg_id(id);
if (id >= num_args_)
this->on_error("argument not found");
}
using base::check_arg_id;
};
template <typename Char, typename ErrorHandler, typename... Args>
class format_string_checker {
public:
explicit constexpr format_string_checker(basic_string_view<Char> format_str,
ErrorHandler eh)
: context_(format_str, num_args, eh),
parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {
}
constexpr void on_text(const Char*, const Char*) {
}
constexpr int on_arg_id() {
return context_.next_arg_id();
}
constexpr int on_arg_id(int id) {
return context_.check_arg_id(id), id;
}
constexpr int on_arg_id(basic_string_view<Char>) {
on_error("compile-time checks don't support named arguments");
return 0;
}
constexpr void on_replacement_field(int, const Char*) {
}
constexpr const Char* on_format_specs(int id,
const Char* begin,
const Char*) {
advance_to(context_, begin);
return id < num_args ? parse_funcs_[id](context_) : begin;
}
constexpr void on_error(const char* message) {
context_.on_error(message);
}
private:
using parse_context_type = compile_parse_context<Char, ErrorHandler>;
enum { num_args = sizeof...(Args) };
using parse_func = const Char* (*)(parse_context_type&);
parse_context_type context_;
parse_func parse_funcs_[num_args > 0 ? num_args : 1];
};
template <typename Char, size_t N>
constexpr basic_string_view<Char> compile_string_to_view(const Char (&s)[N]) {
return {s,
N - ((std::char_traits<Char>::to_int_type(s[N - 1]) == 0) ? 1 : 0)};
}
template <typename Char>
constexpr basic_string_view<Char> compile_string_to_view(
const std_string_view<Char>& s) {
return {s.data(), s.size()};
}
// # 3221 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename... Args,
typename S,
enable_if_t<(is_compile_string<S>::value), int>>
void check_format_string(S format_str) {
constexpr auto s = to_string_view(format_str);
using checker = format_string_checker<typename S::char_type,
error_handler,
remove_cvref_t<Args>...>;
constexpr bool invalid_format =
(parse_format_string<true>(s, checker(s, {})), true);
(void)invalid_format;
}
template <template <typename> class Handler, typename Context>
void handle_dynamic_spec(int& value,
arg_ref<typename Context::char_type> ref,
Context& ctx) {
switch (ref.kind) {
case arg_id_kind::none:
break;
case arg_id_kind::index:
value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
ctx.error_handler());
break;
case arg_id_kind::name:
value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
ctx.error_handler());
break;
}
}
using format_func = void (*)(detail::buffer<char>&, int, string_view);
void format_error_code(buffer<char>& out,
int error_code,
string_view message) noexcept;
void report_error(format_func func,
int error_code,
string_view message) noexcept;
} // namespace detail
template <typename OutputIt, typename Char>
using arg_formatter [[deprecated]] = detail::arg_formatter<OutputIt, Char>;
class system_error : public std::runtime_error {
private:
void init(int err_code, string_view format_str, format_args args);
protected:
int error_code_;
system_error() : std::runtime_error(""), error_code_(0) {
}
public:
// # 3295 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename... Args>
system_error(int error_code, string_view message, const Args&... args)
: std::runtime_error("") {
init(error_code, message, make_format_args(args...));
}
system_error(const system_error&) = default;
system_error& operator=(const system_error&) = default;
system_error(system_error&&) = default;
system_error& operator=(system_error&&) = default;
~system_error() noexcept override;
int error_code() const {
return error_code_;
}
};
// # 3325 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
void format_system_error(detail::buffer<char>& out,
int error_code,
string_view message) noexcept;
void report_system_error(int error_code, string_view message) noexcept;
class format_int {
private:
enum {
buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3
};
mutable char buffer_[buffer_size];
char* str_;
template <typename UInt>
char* format_unsigned(UInt value) {
auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
}
template <typename Int>
char* format_signed(Int value) {
auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
bool negative = value < 0;
if (negative)
abs_value = 0 - abs_value;
auto begin = format_unsigned(abs_value);
if (negative)
*--begin = '-';
return begin;
}
public:
explicit format_int(int value) : str_(format_signed(value)) {
}
explicit format_int(long value) : str_(format_signed(value)) {
}
explicit format_int(long long value) : str_(format_signed(value)) {
}
explicit format_int(unsigned value) : str_(format_unsigned(value)) {
}
explicit format_int(unsigned long value) : str_(format_unsigned(value)) {
}
explicit format_int(unsigned long long value)
: str_(format_unsigned(value)) {
}
size_t size() const {
return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
}
const char* data() const {
return str_;
}
const char* c_str() const {
buffer_[buffer_size - 1] = '\0';
return str_;
}
std::string str() const {
return std::string(str_, size());
}
};
template <typename T, typename Char>
struct formatter<T,
Char,
enable_if_t<detail::type_constant<T, Char>::value !=
detail::type::custom_type>> {
constexpr formatter() = default;
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
using handler_type = detail::dynamic_specs_handler<ParseContext>;
auto type = detail::type_constant<T, Char>::value;
detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
type);
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
auto eh = ctx.error_handler();
switch (type) {
case detail::type::none_type:
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
3413,
("invalid argument type")));
break;
case detail::type::int_type:
case detail::type::uint_type:
case detail::type::long_long_type:
case detail::type::ulong_long_type:
case detail::type::int128_type:
case detail::type::uint128_type:
case detail::type::bool_type:
handle_int_type_spec(specs_.type,
detail::int_type_checker<decltype(eh)>(eh));
break;
case detail::type::char_type:
handle_char_specs(
&specs_,
detail::char_specs_checker<decltype(eh)>(specs_.type, eh));
break;
case detail::type::float_type:
if (detail::const_check(1))
detail::parse_float_type_spec(specs_, eh);
else
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
3433,
("float support disabled")));
break;
case detail::type::double_type:
if (detail::const_check(1))
detail::parse_float_type_spec(specs_, eh);
else
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
3439,
("double support disabled")));
break;
case detail::type::long_double_type:
if (detail::const_check(1))
detail::parse_float_type_spec(specs_, eh);
else
((false) ? (void)0
: ::fmt::detail::assert_fail(
"tlm/deps/fmt.exploded/include/fmt/format.h",
3445,
("long double support disabled")));
break;
case detail::type::cstring_type:
detail::handle_cstring_type_spec(
specs_.type,
detail::cstring_type_checker<decltype(eh)>(eh));
break;
case detail::type::string_type:
detail::check_string_type_spec(specs_.type, eh);
break;
case detail::type::pointer_type:
detail::check_pointer_type_spec(specs_.type, eh);
break;
case detail::type::custom_type:
break;
}
return it;
}
template <typename FormatContext>
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
detail::handle_dynamic_spec<detail::width_checker>(
specs_.width, specs_.width_ref, ctx);
detail::handle_dynamic_spec<detail::precision_checker>(
specs_.precision, specs_.precision_ref, ctx);
using af = detail::arg_formatter<typename FormatContext::iterator,
typename FormatContext::char_type>;
return visit_format_arg(af(ctx, nullptr, &specs_),
detail::make_arg<FormatContext>(val));
}
private:
detail::dynamic_format_specs<Char> specs_;
};
// # 3490 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename Char>
struct formatter<signed char, Char> : formatter<int, Char> {
template <typename FormatContext>
auto format(signed char const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<int, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<unsigned char, Char> : formatter<unsigned, Char> {
template <typename FormatContext>
auto format(unsigned char const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<unsigned, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<short, Char> : formatter<int, Char> {
template <typename FormatContext>
auto format(short const& val, FormatContext& ctx) -> decltype(ctx.out()) {
return formatter<int, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<unsigned short, Char> : formatter<unsigned, Char> {
template <typename FormatContext>
auto format(unsigned short const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<unsigned, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<long, Char> : formatter<long long, Char> {
template <typename FormatContext>
auto format(long const& val, FormatContext& ctx) -> decltype(ctx.out()) {
return formatter<long long, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<unsigned long, Char> : formatter<unsigned long long, Char> {
template <typename FormatContext>
auto format(unsigned long const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<unsigned long long, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<Char*, Char> : formatter<const Char*, Char> {
template <typename FormatContext>
auto format(Char* const& val, FormatContext& ctx) -> decltype(ctx.out()) {
return formatter<const Char*, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<std::basic_string<Char>, Char>
: formatter<basic_string_view<Char>, Char> {
template <typename FormatContext>
auto format(std::basic_string<Char> const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<basic_string_view<Char>, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<std::nullptr_t, Char> : formatter<const void*, Char> {
template <typename FormatContext>
auto format(std::nullptr_t const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<const void*, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<detail::std_string_view<Char>, Char>
: formatter<basic_string_view<Char>, Char> {
template <typename FormatContext>
auto format(detail::std_string_view<Char> const& val, FormatContext& ctx)
-> decltype(ctx.out()) {
return formatter<basic_string_view<Char>, Char>::format(val, ctx);
}
};
template <typename Char>
struct formatter<void*, Char> : formatter<const void*, Char> {
template <typename FormatContext>
auto format(void* val, FormatContext& ctx) -> decltype(ctx.out()) {
return formatter<const void*, Char>::format(val, ctx);
}
};
template <typename Char, size_t N>
struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
template <typename FormatContext>
auto format(const Char* val, FormatContext& ctx) -> decltype(ctx.out()) {
return formatter<basic_string_view<Char>, Char>::format(val, ctx);
}
};
// # 3529 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename Char = char>
class dynamic_formatter {
private:
struct null_handler : detail::error_handler {
void on_align(align_t) {
}
void on_plus() {
}
void on_minus() {
}
void on_space() {
}
void on_hash() {
}
};
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
format_str_ = ctx.begin();
detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
return parse_format_specs(ctx.begin(), ctx.end(), handler);
}
template <typename T, typename FormatContext>
auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
handle_specs(ctx);
detail::specs_checker<null_handler> checker(
null_handler(),
detail::mapped_type_constant<T, FormatContext>::value);
checker.on_align(specs_.align);
switch (specs_.sign) {
case sign::none:
break;
case sign::plus:
checker.on_plus();
break;
case sign::minus:
checker.on_minus();
break;
case sign::space:
checker.on_space();
break;
}
if (specs_.alt)
checker.on_hash();
if (specs_.precision >= 0)
checker.end_precision();
using af = detail::arg_formatter<typename FormatContext::iterator,
typename FormatContext::char_type>;
visit_format_arg(af(ctx, nullptr, &specs_),
detail::make_arg<FormatContext>(val));
return ctx.out();
}
private:
template <typename Context>
void handle_specs(Context& ctx) {
detail::handle_dynamic_spec<detail::width_checker>(
specs_.width, specs_.width_ref, ctx);
detail::handle_dynamic_spec<detail::precision_checker>(
specs_.precision, specs_.precision_ref, ctx);
}
detail::dynamic_format_specs<Char> specs_;
const Char* format_str_;
};
template <typename Char, typename ErrorHandler>
constexpr void advance_to(basic_format_parse_context<Char, ErrorHandler>& ctx,
const Char* p) {
ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
}
// # 3603 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename T>
inline const void* ptr(const T* p) {
return p;
}
template <typename T>
inline const void* ptr(const std::unique_ptr<T>& p) {
return p.get();
}
template <typename T>
inline const void* ptr(const std::shared_ptr<T>& p) {
return p.get();
}
class bytes {
private:
string_view data_;
friend struct formatter<bytes>;
public:
explicit bytes(string_view data) : data_(data) {
}
};
template <>
struct formatter<bytes> {
private:
detail::dynamic_format_specs<char> specs_;
public:
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
using handler_type = detail::dynamic_specs_handler<ParseContext>;
detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
detail::type::string_type);
auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
detail::check_string_type_spec(specs_.type, ctx.error_handler());
return it;
}
template <typename FormatContext>
auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
detail::handle_dynamic_spec<detail::width_checker>(
specs_.width, specs_.width_ref, ctx);
detail::handle_dynamic_spec<detail::precision_checker>(
specs_.precision, specs_.precision_ref, ctx);
return detail::write_bytes(ctx.out(), b.data_, specs_);
}
};
template <typename It, typename Sentinel, typename Char>
struct arg_join : detail::view {
It begin;
Sentinel end;
basic_string_view<Char> sep;
arg_join(It b, Sentinel e, basic_string_view<Char> s)
: begin(b), end(e), sep(s) {
}
};
template <typename It, typename Sentinel, typename Char>
struct formatter<arg_join<It, Sentinel, Char>, Char>
: formatter<typename std::iterator_traits<It>::value_type, Char> {
template <typename FormatContext>
auto format(const arg_join<It, Sentinel, Char>& value, FormatContext& ctx)
-> decltype(ctx.out()) {
using base =
formatter<typename std::iterator_traits<It>::value_type, Char>;
auto it = value.begin;
auto out = ctx.out();
if (it != value.end) {
out = base::format(*it++, ctx);
while (it != value.end) {
out = std::copy(value.sep.begin(), value.sep.end(), out);
ctx.advance_to(out);
out = base::format(*it++, ctx);
}
}
return out;
}
};
template <typename It, typename Sentinel>
arg_join<It, Sentinel, char> join(It begin, Sentinel end, string_view sep) {
return {begin, end, sep};
}
template <typename It, typename Sentinel>
arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
return {begin, end, sep};
}
// # 3706 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename Range>
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, char> join(
Range&& range, string_view sep) {
return join(std::begin(range), std::end(range), sep);
}
template <typename Range>
arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, wchar_t> join(
Range&& range, wstring_view sep) {
return join(std::begin(range), std::end(range), sep);
}
// # 3729 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename T, enable_if_t<(!std::is_integral<T>::value), int> = 0>
inline std::string to_string(const T& value) {
std::string result;
detail::write<char>(std::back_inserter(result), value);
return result;
}
template <typename T, enable_if_t<(std::is_integral<T>::value), int> = 0>
inline std::string to_string(T value) {
constexpr int max_size = detail::digits10<T>() + 2;
char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
char* begin = buffer;
return std::string(begin, detail::write<char>(begin, value));
}
template <typename T>
inline std::wstring to_wstring(const T& value) {
return format(L"{}", value);
}
template <typename Char, size_t SIZE>
std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
auto size = buf.size();
detail::assume(size < std::basic_string<Char>().max_size());
return std::basic_string<Char>(buf.data(), size);
}
template <typename Char>
void detail::vformat_to(
detail::buffer<Char>& buf,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args,
detail::locale_ref loc) {
using iterator = typename buffer_context<Char>::iterator;
auto out = buffer_appender<Char>(buf);
if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
auto arg = args.get(0);
if (!arg)
error_handler().on_error("argument not found");
visit_format_arg(default_arg_formatter<iterator, Char>{out, args, loc},
arg);
return;
}
format_handler<iterator, Char, buffer_context<Char>> h(
out, format_str, args, loc);
parse_format_string<false>(format_str, h);
}
extern template void detail::vformat_to(detail::buffer<char>&,
string_view,
basic_format_args<format_context>,
detail::locale_ref);
namespace detail {
extern template std::string grouping_impl<char>(locale_ref loc);
extern template std::string grouping_impl<wchar_t>(locale_ref loc);
extern template char thousands_sep_impl<char>(locale_ref loc);
extern template wchar_t thousands_sep_impl<wchar_t>(locale_ref loc);
extern template char decimal_point_impl(locale_ref loc);
extern template wchar_t decimal_point_impl(locale_ref loc);
extern template int format_float<double>(double value,
int precision,
float_specs specs,
buffer<char>& buf);
extern template int format_float<long double>(long double value,
int precision,
float_specs specs,
buffer<char>& buf);
int snprintf_float(float value,
int precision,
float_specs specs,
buffer<char>& buf) = delete;
extern template int snprintf_float<double>(double value,
int precision,
float_specs specs,
buffer<char>& buf);
extern template int snprintf_float<long double>(long double value,
int precision,
float_specs specs,
buffer<char>& buf);
} // namespace detail
template <typename S,
typename Char = char_t<S>,
enable_if_t<(detail::is_string<S>::value), int> = 0>
inline void vformat_to(detail::buffer<Char>& buf,
const S& format_str,
basic_format_args<basic_format_context<
detail::buffer_appender<type_identity_t<Char>>,
type_identity_t<Char>>> args) {
return detail::vformat_to(buf, to_string_view(format_str), args);
}
template <typename S,
typename... Args,
size_t SIZE = inline_buffer_size,
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
inline typename buffer_context<Char>::iterator format_to(
basic_memory_buffer<Char, SIZE>& buf,
const S& format_str,
Args&&... args) {
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
detail::vformat_to(buf, to_string_view(format_str), vargs);
return detail::buffer_appender<Char>(buf);
}
template <typename OutputIt, typename Char = char>
using format_context_t = basic_format_context<OutputIt, Char>;
template <typename OutputIt, typename Char = char>
using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
template <typename OutputIt, typename Char = typename OutputIt::value_type>
using format_to_n_context [[deprecated]] = buffer_context<Char>;
template <typename OutputIt, typename Char = typename OutputIt::value_type>
using format_to_n_args [[deprecated]] = basic_format_args<buffer_context<Char>>;
template <typename OutputIt, typename Char, typename... Args>
[[deprecated]] format_arg_store<buffer_context<Char>, Args...>
make_format_to_n_args(const Args&... args) {
return format_arg_store<buffer_context<Char>, Args...>(args...);
}
template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
std::basic_string<Char> detail::vformat(
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer;
detail::vformat_to(buffer, format_str, args);
return to_string(buffer);
}
template <typename Char,
enable_if_t<(std::is_same<Char, wchar_t>::value), int> = 0>
void vprint(std::FILE* f,
basic_string_view<Char> format_str,
wformat_args args) {
wmemory_buffer buffer;
detail::vformat_to(buffer, format_str, args);
buffer.push_back(L'\0');
if (std::fputws(buffer.data(), f) == -1)
throw system_error((*__errno_location()), "cannot write to file");
}
template <typename Char,
enable_if_t<(std::is_same<Char, wchar_t>::value), int> = 0>
void vprint(basic_string_view<Char> format_str, wformat_args args) {
vprint(stdout, format_str, args);
}
namespace detail {
template <typename Char, Char... CHARS>
class udl_formatter {
public:
template <typename... Args>
std::basic_string<Char> operator()(Args&&... args) const {
static constexpr Char s[] = {CHARS..., '\0'};
return format(
[] {
struct FMT_COMPILE_STRING : fmt::compile_string {
using char_type = fmt::remove_cvref_t<decltype(s[0])>;
[[maybe_unused]] constexpr
operator fmt::basic_string_view<char_type>() const {
return fmt::detail::compile_string_to_view<
char_type>(s);
}
};
return FMT_COMPILE_STRING();
}(),
std::forward<Args>(args)...);
}
};
// # 3891 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
template <typename Char>
struct udl_arg {
const Char* str;
template <typename T>
named_arg<Char, T> operator=(T&& value) const {
return {str, std::forward<T>(value)};
}
};
} // namespace detail
inline namespace literals {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
template <typename Char, Char... CHARS>
constexpr detail::udl_formatter<Char, CHARS...> operator""_format() {
return {};
}
#pragma GCC diagnostic pop
// # 3943 "tlm/deps/fmt.exploded/include/fmt/format.h" 3 4
constexpr detail::udl_arg<char> operator"" _a(const char* s, size_t) {
return {s};
}
constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
return {s};
}
} // namespace literals
} // namespace v7
} // namespace fmt
// # 27 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/fmt.h"
// 2 # 37
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h" 2 #
// 81 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
// # 81 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
namespace spdlog {
class formatter;
namespace sinks {
class sink;
}
using filename_t = std::string;
using log_clock = std::chrono::system_clock;
using sink_ptr = std::shared_ptr<sinks::sink>;
using sinks_init_list = std::initializer_list<sink_ptr>;
using err_handler = std::function<void(const std::string& err_msg)>;
using string_view_t = fmt::basic_string_view<char>;
using wstring_view_t = fmt::basic_string_view<wchar_t>;
using memory_buf_t = fmt::basic_memory_buffer<char, 250>;
using wmemory_buf_t = fmt::basic_memory_buffer<wchar_t, 250>;
// # 117 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
template <typename>
struct is_convertible_to_wstring_view : std::false_type {};
using level_t = std::atomic<int>;
// # 141 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
namespace level {
enum level_enum {
trace = 0,
debug = 1,
info = 2,
warn = 3,
err = 4,
critical = 5,
off = 6,
n_levels
};
// # 169 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
const string_view_t& to_string_view(spdlog::level::level_enum l) noexcept;
void set_string_view(spdlog::level::level_enum l,
const string_view_t& s) noexcept;
const char* to_short_c_str(spdlog::level::level_enum l) noexcept;
spdlog::level::level_enum from_str(const std::string& name) noexcept;
} // namespace level
enum class color_mode { always, automatic, never };
enum class pattern_time_type { local, utc };
class spdlog_ex : public std::exception {
public:
explicit spdlog_ex(std::string msg);
spdlog_ex(const std::string& msg, int last_errno);
const char* what() const noexcept override;
private:
std::string msg_;
};
[[noreturn]] void throw_spdlog_ex(const std::string& msg, int last_errno);
[[noreturn]] void throw_spdlog_ex(std::string msg);
struct source_loc {
constexpr source_loc() = default;
constexpr source_loc(const char* filename_in,
int line_in,
const char* funcname_in)
: filename{filename_in}, line{line_in}, funcname{funcname_in} {
}
constexpr bool empty() const noexcept {
return line == 0;
}
const char* filename{nullptr};
int line{0};
const char* funcname{nullptr};
};
namespace details {
using std::make_unique;
// # 244 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/common.h"
} // namespace details
} // namespace spdlog
// # 18 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
// 2 # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/log_msg.h"
// 1
namespace spdlog {
namespace details {
struct log_msg {
log_msg() = default;
log_msg(log_clock::time_point log_time,
source_loc loc,
string_view_t logger_name,
level::level_enum lvl,
string_view_t msg);
log_msg(source_loc loc,
string_view_t logger_name,
level::level_enum lvl,
string_view_t msg);
log_msg(string_view_t logger_name,
level::level_enum lvl,
string_view_t msg);
log_msg(const log_msg& other) = default;
string_view_t logger_name;
level::level_enum level{level::off};
log_clock::time_point time;
size_t thread_id{0};
mutable size_t color_range_start{0};
mutable size_t color_range_end{0};
source_loc source;
string_view_t payload;
};
} // namespace details
} // namespace spdlog
// # 19 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
// 2 # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/backtracer.h"
// 1
// # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/log_msg_buffer.h"
// 1
namespace spdlog {
namespace details {
class log_msg_buffer : public log_msg {
memory_buf_t buffer;
void update_string_views();
public:
log_msg_buffer() = default;
explicit log_msg_buffer(const log_msg& orig_msg);
log_msg_buffer(const log_msg_buffer& other);
log_msg_buffer(log_msg_buffer&& other) noexcept;
log_msg_buffer& operator=(const log_msg_buffer& other);
log_msg_buffer& operator=(log_msg_buffer&& other) noexcept;
};
} // namespace details
} // namespace spdlog
// # 7
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/backtracer.h"
// 2 # 1
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
// 1
// # 9
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
// 2
namespace spdlog {
namespace details {
template <typename T>
class circular_q {
size_t max_items_ = 0;
typename std::vector<T>::size_type head_ = 0;
typename std::vector<T>::size_type tail_ = 0;
size_t overrun_counter_ = 0;
std::vector<T> v_;
public:
using value_type = T;
circular_q() = default;
explicit circular_q(size_t max_items)
: max_items_(max_items + 1), v_(max_items_) {
}
circular_q(const circular_q&) = default;
circular_q& operator=(const circular_q&) = default;
circular_q(circular_q&& other) noexcept {
copy_moveable(std::move(other));
}
circular_q& operator=(circular_q&& other) noexcept {
copy_moveable(std::move(other));
return *this;
}
void push_back(T&& item) {
if (max_items_ > 0) {
v_[tail_] = std::move(item);
tail_ = (tail_ + 1) % max_items_;
if (tail_ == head_) {
head_ = (head_ + 1) % max_items_;
++overrun_counter_;
}
}
}
const T& front() const {
return v_[head_];
}
T& front() {
return v_[head_];
}
size_t size() const {
if (tail_ >= head_) {
return tail_ - head_;
} else {
return max_items_ - (head_ - tail_);
}
}
const T& at(size_t i) const {
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
// 3 4
(static_cast<bool>(
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
i < size()
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
// 3 4
)
? void(0)
: __assert_fail(
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
"i < size()"
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
// 3 4
,
"/mnt/Code/couchbase/docker/third_party/spdlog/"
"include/spdlog/details/circular_q.h",
93,
__extension__ __PRETTY_FUNCTION__))
// # 93
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/circular_q.h"
;
return v_[(head_ + i) % max_items_];
}
void pop_front() {
head_ = (head_ + 1) % max_items_;
}
bool empty() const {
return tail_ == head_;
}
bool full() const {
if (max_items_ > 0) {
return ((tail_ + 1) % max_items_) == head_;
}
return false;
}
size_t overrun_counter() const {
return overrun_counter_;
}
private:
void copy_moveable(circular_q&& other) noexcept {
max_items_ = other.max_items_;
head_ = other.head_;
tail_ = other.tail_;
overrun_counter_ = other.overrun_counter_;
v_ = std::move(other.v_);
other.max_items_ = 0;
other.head_ = other.tail_ = 0;
other.overrun_counter_ = 0;
}
};
} // namespace details
} // namespace spdlog
// # 8
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/backtracer.h"
// 2
// # 11
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/backtracer.h"
// 2
// # 16
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/details/backtracer.h"
namespace spdlog {
namespace details {
class backtracer {
mutable std::mutex mutex_;
std::atomic<bool> enabled_{false};
circular_q<log_msg_buffer> messages_;
public:
backtracer() = default;
backtracer(const backtracer& other);
backtracer(backtracer&& other) noexcept;
backtracer& operator=(backtracer other);
void enable(size_t size);
void disable();
bool enabled() const;
void push_back(const log_msg& msg);
void foreach_pop(std::function<void(const details::log_msg&)> fun);
};
} // namespace details
} // namespace spdlog
// # 20 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
// 2 # 40
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
namespace spdlog {
class logger {
public:
explicit logger(std::string name) : name_(std::move(name)), sinks_() {
}
template <typename It>
logger(std::string name, It begin, It end)
: name_(std::move(name)), sinks_(begin, end) {
}
logger(std::string name, sink_ptr single_sink)
: logger(std::move(name), {std::move(single_sink)}) {
}
logger(std::string name, sinks_init_list sinks)
: logger(std::move(name), sinks.begin(), sinks.end()) {
}
virtual ~logger() = default;
logger(const logger& other);
logger(logger&& other) noexcept;
logger& operator=(logger other) noexcept;
void swap(spdlog::logger& other) noexcept;
template <
typename FormatString,
typename std::enable_if<fmt::is_compile_string<FormatString>::value,
int>::type = 0,
typename... Args>
void log(source_loc loc,
level::level_enum lvl,
const FormatString& fmt,
Args&&... args) {
log_(loc, lvl, fmt, std::forward<Args>(args)...);
}
template <typename... Args>
void log(source_loc loc,
level::level_enum lvl,
string_view_t fmt,
Args&&... args) {
log_(loc, lvl, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void log(level::level_enum lvl, const FormatString& fmt, Args&&... args) {
log(source_loc{}, lvl, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void trace(const FormatString& fmt, Args&&... args) {
log(level::trace, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void debug(const FormatString& fmt, Args&&... args) {
log(level::debug, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void info(const FormatString& fmt, Args&&... args) {
log(level::info, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void warn(const FormatString& fmt, Args&&... args) {
log(level::warn, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void error(const FormatString& fmt, Args&&... args) {
log(level::err, fmt, std::forward<Args>(args)...);
}
template <typename FormatString, typename... Args>
void critical(const FormatString& fmt, Args&&... args) {
log(level::critical, fmt, std::forward<Args>(args)...);
}
template <typename T>
void log(level::level_enum lvl, const T& msg) {
log(source_loc{}, lvl, msg);
}
template <class T,
typename std::enable_if<
std::is_convertible<const T&,
spdlog::string_view_t>::value &&
!fmt::is_compile_string<T>::value,
int>::type = 0>
void log(source_loc loc, level::level_enum lvl, const T& msg) {
log(loc, lvl, string_view_t{msg});
}
void log(log_clock::time_point log_time,
source_loc loc,
level::level_enum lvl,
string_view_t msg) {
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled) {
return;
}
details::log_msg log_msg(log_time, loc, name_, lvl, msg);
log_it_(log_msg, log_enabled, traceback_enabled);
}
void log(source_loc loc, level::level_enum lvl, string_view_t msg) {
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled) {
return;
}
details::log_msg log_msg(loc, name_, lvl, msg);
log_it_(log_msg, log_enabled, traceback_enabled);
}
void log(level::level_enum lvl, string_view_t msg) {
log(source_loc{}, lvl, msg);
}
template <class T,
typename std::enable_if<
!std::is_convertible<const T&,
spdlog::string_view_t>::value &&
!is_convertible_to_wstring_view<const T&>::value,
int>::type = 0>
void log(source_loc loc, level::level_enum lvl, const T& msg) {
log(loc, lvl, "{}", msg);
}
template <typename T>
void trace(const T& msg) {
log(level::trace, msg);
}
template <typename T>
void debug(const T& msg) {
log(level::debug, msg);
}
template <typename T>
void info(const T& msg) {
log(level::info, msg);
}
template <typename T>
void warn(const T& msg) {
log(level::warn, msg);
}
template <typename T>
void error(const T& msg) {
log(level::err, msg);
}
template <typename T>
void critical(const T& msg) {
log(level::critical, msg);
}
// # 274
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/logger.h"
bool should_log(level::level_enum msg_level) const {
return msg_level >= level_.load(std::memory_order_relaxed);
}
bool should_backtrace() const {
return tracer_.enabled();
}
void set_level(level::level_enum log_level);
level::level_enum level() const;
const std::string& name() const;
void set_formatter(std::unique_ptr<formatter> f);
void set_pattern(std::string pattern,
pattern_time_type time_type = pattern_time_type::local);
void enable_backtrace(size_t n_messages);
void disable_backtrace();
void dump_backtrace();
void flush();
void flush_on(level::level_enum log_level);
level::level_enum flush_level() const;
const std::vector<sink_ptr>& sinks() const;
std::vector<sink_ptr>& sinks();
void set_error_handler(err_handler);
virtual std::shared_ptr<logger> clone(std::string logger_name);
protected:
std::string name_;
std::vector<sink_ptr> sinks_;
spdlog::level_t level_{level::info};
spdlog::level_t flush_level_{level::off};
err_handler custom_err_handler_{nullptr};
details::backtracer tracer_;
template <typename FormatString, typename... Args>
void log_(source_loc loc,
level::level_enum lvl,
const FormatString& fmt,
Args&&... args) {
bool log_enabled = should_log(lvl);
bool traceback_enabled = tracer_.enabled();
if (!log_enabled && !traceback_enabled) {
return;
}
try {
memory_buf_t buf;
fmt::format_to(buf, fmt, std::forward<Args>(args)...);
details::log_msg log_msg(
loc, name_, lvl, string_view_t(buf.data(), buf.size()));
log_it_(log_msg, log_enabled, traceback_enabled);
} catch (const std::exception& ex) {
err_handler_(ex.what());
} catch (...) {
err_handler_("Unknown exception in logger");
}
}
void log_it_(const details::log_msg& log_msg,
bool log_enabled,
bool traceback_enabled);
virtual void sink_it_(const details::log_msg& msg);
virtual void flush_();
void dump_backtrace_();
bool should_flush_(const details::log_msg& msg);
void err_handler_(const std::string& msg);
};
void swap(logger& a, logger& b);
} // namespace spdlog
// # 15 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h" 2
// # 1
// "/mnt/Code/couchbase/docker/kv_engine/include/memcached/server_log_iface.h" 1
// # 12
// "/mnt/Code/couchbase/docker/kv_engine/include/memcached/server_log_iface.h"
namespace spdlog {
class logger;
}
struct ServerLogIface {
virtual ~ServerLogIface() = default;
virtual spdlog::logger* get_spdlogger() = 0;
virtual void register_spdlogger(std::shared_ptr<spdlog::logger> logger) = 0;
virtual void unregister_spdlogger(const std::string& name) = 0;
virtual void set_level(spdlog::level::level_enum severity) = 0;
};
// # 17 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h" 2
class EventuallyPersistentEngine;
const std::string globalBucketLoggerName = "globalBucketLogger";
// # 87 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
class BucketLogger : public spdlog::logger {
public:
// # 97
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
template <typename S, typename... Args>
void log(spdlog::level::level_enum lvl, const S& fmt, Args&&... args);
template <typename... Args>
void log(spdlog::level::level_enum lvl, const char* msg);
template <typename T>
void log(spdlog::level::level_enum lvl, const T& msg);
template <typename... Args>
void trace(const char* fmt, const Args&... args);
template <typename... Args>
void debug(const char* fmt, const Args&... args);
template <typename... Args>
void info(const char* fmt, const Args&... args);
template <typename... Args>
void warn(const char* fmt, const Args&... args);
template <typename... Args>
void error(const char* fmt, const Args&... args);
template <typename... Args>
void critical(const char* fmt, const Args&... args);
template <typename T>
void trace(const T& msg);
template <typename T>
void debug(const T& msg);
template <typename T>
void info(const T& msg);
template <typename T>
void warn(const T& msg);
template <typename T>
void error(const T& msg);
template <typename T>
void critical(const T& msg);
static void setLoggerAPI(ServerLogIface* api);
// # 159
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
static std::shared_ptr<BucketLogger> createBucketLogger(
const std::string& name, const std::string& prefix = "");
void setConnectionId(uint32_t id) {
this->connectionId = id;
}
std::string prefix;
void unregister();
protected:
void sink_it_(const spdlog::details::log_msg& msg) override;
void flush_() override;
void logInner(spdlog::level::level_enum lvl,
fmt::string_view fmt,
fmt::format_args args);
std::string prefixStringWithBucketName(
const EventuallyPersistentEngine* engine, fmt::string_view fmt);
uint32_t connectionId{0};
// # 214
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
explicit BucketLogger(const std::string& name, std::string prefix = "");
static ServerLogIface* getServerLogIface();
private:
static std::atomic<ServerLogIface*> loggerAPI;
spdlog::logger* spdLogger;
static std::mutex initGuard;
};
std::shared_ptr<BucketLogger>& getGlobalBucketLogger();
// # 319 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h"
// # 1
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger_impl.h" 1
// # 11
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger_impl.h"
// # 1 "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/ostr.h"
// 1
// # 19
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/ostr.h" # 1
// "tlm/deps/fmt.exploded/include/fmt/ostream.h" 1 3 4 # 13
// "tlm/deps/fmt.exploded/include/fmt/ostream.h" 3 4 # 1
// "tlm/deps/fmt.exploded/include/fmt/format.h" 1 3 4 # 14
// "tlm/deps/fmt.exploded/include/fmt/ostream.h" 2 3 4
// # 15 "tlm/deps/fmt.exploded/include/fmt/ostream.h" 3 4
namespace fmt {
inline namespace v7 {
template <typename Char>
class basic_printf_parse_context;
template <typename OutputIt, typename Char>
class basic_printf_context;
namespace detail {
template <class Char>
class formatbuf : public std::basic_streambuf<Char> {
private:
using int_type = typename std::basic_streambuf<Char>::int_type;
using traits_type = typename std::basic_streambuf<Char>::traits_type;
buffer<Char>& buffer_;
public:
formatbuf(buffer<Char>& buf) : buffer_(buf) {
}
protected:
int_type overflow(int_type ch = traits_type::eof()) override {
if (!traits_type::eq_int_type(ch, traits_type::eof()))
buffer_.push_back(static_cast<Char>(ch));
return ch;
}
std::streamsize xsputn(const Char* s, std::streamsize count) override {
buffer_.append(s, s + count);
return count;
}
};
struct converter {
template <typename T, enable_if_t<(is_integral<T>::value), int> = 0>
converter(T);
};
template <typename Char>
struct test_stream : std::basic_ostream<Char> {
private:
void_t<> operator<<(converter);
};
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char);
template <typename Char, typename Traits>
void_t<> operator<<(std::basic_ostream<Char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char);
template <typename Traits>
void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char);
template <typename T, typename Char>
class is_streamable {
private:
template <typename U>
static bool_constant<!std::is_same<
decltype(std::declval<test_stream<Char>&>() << std::declval<U>()),
void_t<>>::value>
test(int);
template <typename>
static std::false_type test(...);
using result = decltype(test<T>(0));
public:
static const bool value = result::value;
};
template <typename Char>
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
const Char* buf_data = buf.data();
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
unsigned_streamsize size = buf.size();
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
do {
unsigned_streamsize n = size <= max_size ? size : max_size;
os.write(buf_data, static_cast<std::streamsize>(n));
buf_data += n;
size -= n;
} while (size != 0);
}
template <typename Char, typename T>
void format_value(buffer<Char>& buf,
const T& value,
locale_ref loc = locale_ref()) {
formatbuf<Char> format_buf(buf);
std::basic_ostream<Char> output(&format_buf);
if (loc)
output.imbue(loc.get<std::locale>());
output << value;
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
buf.try_resize(buf.size());
}
template <typename T, typename Char>
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
: private formatter<basic_string_view<Char>, Char> {
constexpr auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
return formatter<basic_string_view<Char>, Char>::parse(ctx);
}
template <
typename ParseCtx,
enable_if_t<(std::is_same<ParseCtx,
basic_printf_parse_context<Char>>::value),
int> = 0>
auto parse(ParseCtx& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
template <typename OutputIt>
auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
-> OutputIt {
basic_memory_buffer<Char> buffer;
format_value(buffer, value, ctx.locale());
basic_string_view<Char> str(buffer.data(), buffer.size());
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
}
template <typename OutputIt>
auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
-> OutputIt {
basic_memory_buffer<Char> buffer;
format_value(buffer, value, ctx.locale());
return std::copy(buffer.begin(), buffer.end(), ctx.out());
}
};
} // namespace detail
template <typename Char>
void vprint(std::basic_ostream<Char>& os,
basic_string_view<Char> format_str,
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer;
detail::vformat_to(buffer, format_str, args);
detail::write_buffer(os, buffer);
}
// # 169 "tlm/deps/fmt.exploded/include/fmt/ostream.h" 3 4
template <typename S,
typename... Args,
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
vprint(os,
to_string_view(format_str),
fmt::make_args_checked<Args...>(format_str, args...));
}
} // namespace v7
} // namespace fmt
// # 20
// "/mnt/Code/couchbase/docker/third_party/spdlog/include/spdlog/fmt/ostr.h" 2
// # 14
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger_impl.h" 2
// # 19
// "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger_impl.h"
template <typename S, typename... Args>
void BucketLogger::log(spdlog::level::level_enum lvl,
const S& fmt,
Args&&... args) {
if (!should_log(lvl)) {
return;
}
logInner(lvl, fmt, fmt::make_args_checked<Args...>(fmt, args...));
}
template <typename... Args>
void BucketLogger::log(spdlog::level::level_enum lvl, const char* msg) {
if (!should_log(lvl)) {
return;
}
logInner(lvl, msg, {});
}
template <typename T>
void BucketLogger::log(spdlog::level::level_enum lvl, const T& msg) {
if (!should_log(lvl)) {
return;
}
logInner(lvl, "{}", fmt::make_args_checked<T>("{}", msg));
}
template <typename... Args>
void BucketLogger::trace(const char* fmt, const Args&... args) {
log(spdlog::level::trace, fmt, args...);
}
template <typename... Args>
void BucketLogger::debug(const char* fmt, const Args&... args) {
log(spdlog::level::debug, fmt, args...);
}
template <typename... Args>
void BucketLogger::info(const char* fmt, const Args&... args) {
log(spdlog::level::info, fmt, args...);
}
template <typename... Args>
void BucketLogger::warn(const char* fmt, const Args&... args) {
log(spdlog::level::warn, fmt, args...);
}
template <typename... Args>
void BucketLogger::error(const char* fmt, const Args&... args) {
log(spdlog::level::err, fmt, args...);
}
template <typename... Args>
void BucketLogger::critical(const char* fmt, const Args&... args) {
log(spdlog::level::critical, fmt, args...);
}
template <typename T>
void BucketLogger::trace(const T& msg) {
log(spdlog::level::trace, msg);
}
template <typename T>
void BucketLogger::debug(const T& msg) {
log(spdlog::level::debug, msg);
}
template <typename T>
void BucketLogger::info(const T& msg) {
log(spdlog::level::info, msg);
}
template <typename T>
void BucketLogger::warn(const T& msg) {
log(spdlog::level::warn, msg);
}
template <typename T>
void BucketLogger::error(const T& msg) {
log(spdlog::level::err, msg);
}
template <typename T>
void BucketLogger::critical(const T& msg) {
log(spdlog::level::critical, msg);
}
// # 320 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/bucket_logger.h" 2
// # 15 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc" 2
// # 1 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 1 3 4
// # 82 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 1 3 4
// # 32 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/ThreadCachedInt.h" 1 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/ThreadCachedInt.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Likely.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Likely.h" 3 4
// # 28 "tlm/deps/folly.exploded/include/folly/ThreadCachedInt.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 1 3 4
// # 41 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 3 4
// # 45 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Preprocessor.h" 1 3 4
// # 19 "tlm/deps/folly.exploded/include/folly/Preprocessor.h" 3 4
// # 28 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/CppAttributes.h" 1 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/CppAttributes.h" 3 4
// # 25 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 2 3 4
namespace folly {
template <typename Ex>
[[noreturn]] __attribute__((__noinline__)) __attribute__((__cold__)) void
throw_exception(Ex&& ex) {
throw static_cast<Ex&&>(ex);
}
template <typename Ex>
[[noreturn]] __attribute__((__noinline__)) __attribute__((__cold__)) void
terminate_with(Ex&& ex) noexcept {
throw_exception(static_cast<Ex&&>(ex));
}
namespace detail {
template <typename T>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) T&&
to_exception_arg_(T&& t) {
return static_cast<T&&>(t);
}
template <std::size_t N>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) char const*
to_exception_arg_(char const (&array)[N]) {
return static_cast<char const*>(array);
}
template <typename Ex, typename... Args>
[[noreturn]] __attribute__((__noinline__)) __attribute__((__cold__)) void
throw_exception_(Args&&... args) {
throw_exception(Ex(static_cast<Args&&>(args)...));
}
template <typename Ex, typename... Args>
[[noreturn]] __attribute__((__noinline__)) __attribute__((__cold__)) void
terminate_with_(Args&&... args) noexcept {
throw_exception(Ex(static_cast<Args&&>(args)...));
}
} // namespace detail
// # 80 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
template <typename Ex, typename... Args>
[[noreturn]] inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) void
throw_exception(Args&&... args) {
detail::throw_exception_<Ex>(
detail::to_exception_arg_(static_cast<Args&&>(args))...);
}
template <typename Ex, typename... Args>
[[noreturn]] inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) void
terminate_with(Args&&... args) noexcept {
detail::terminate_with_<Ex>(
detail::to_exception_arg_(static_cast<Args&&>(args))...);
}
// # 117 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
template <typename F, typename... A>
__attribute__((__noinline__)) __attribute__((__cold__)) auto invoke_cold(
F&& f, A&&... a)
-> decltype(static_cast<F&&>(f)(static_cast<A&&>(a)...)) {
return static_cast<F&&>(f)(static_cast<A&&>(a)...);
}
// # 147 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
template <typename F, typename... A>
[[noreturn]] __attribute__((__noinline__)) __attribute__((__cold__)) void
invoke_noreturn_cold(F&& f, A&&... a) {
static_cast<F&&>(f)(static_cast<A&&>(a)...);
std::terminate();
}
// # 183 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
template <typename E, typename Try, typename Catch, typename... CatchA>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) auto
catch_exception(Try&& t, Catch&& c, CatchA&&... a) -> typename std::common_type<
decltype(static_cast<Try&&>(t)()),
decltype(static_cast<Catch&&>(c)(std::declval<E>(),
static_cast<CatchA&&>(a)...))>::type {
try {
return static_cast<Try&&>(t)();
} catch (E e) {
return invoke_cold(
static_cast<Catch&&>(c), e, static_cast<CatchA&&>(a)...);
}
}
// # 223 "tlm/deps/folly.exploded/include/folly/lang/Exception.h" 3 4
template <typename Try, typename Catch, typename... CatchA>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) auto
catch_exception(Try&& t, Catch&& c, CatchA&&... a) -> typename std::common_type<
decltype(static_cast<Try&&>(t)()),
decltype(static_cast<Catch&&>(c)(static_cast<CatchA&&>(a)...))>::type {
try {
return static_cast<Try&&>(t)();
} catch (...) {
return invoke_cold(static_cast<Catch&&>(c),
static_cast<CatchA&&>(a)...);
}
}
[[noreturn]] inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) void
rethrow_current_exception() {
throw;
}
} // namespace folly
// # 30 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/UncaughtExceptions.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/UncaughtExceptions.h" 3 4
namespace __cxxabiv1 {
struct __cxa_eh_globals;
extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept;
} // namespace __cxxabiv1
namespace folly {
inline int uncaught_exceptions() noexcept {
return *(reinterpret_cast<unsigned int*>(
static_cast<char*>(
static_cast<void*>(__cxxabiv1::__cxa_get_globals())) +
sizeof(void*)));
// # 65 "tlm/deps/folly.exploded/include/folly/lang/UncaughtExceptions.h" 3
// 4
}
} // namespace folly
// # 31 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 2 3 4
namespace folly {
namespace detail {
class ScopeGuardImplBase {
public:
void dismiss() noexcept {
dismissed_ = true;
}
protected:
ScopeGuardImplBase() noexcept : dismissed_(false) {
}
static void warnAboutToCrash() noexcept;
static ScopeGuardImplBase makeEmptyScopeGuard() noexcept {
return ScopeGuardImplBase{};
}
template <typename T>
static const T& asConst(const T& t) noexcept {
return t;
}
bool dismissed_;
};
template <typename FunctionType, bool InvokeNoexcept>
class ScopeGuardImpl : public ScopeGuardImplBase {
public:
explicit ScopeGuardImpl(FunctionType& fn) noexcept(
std::is_nothrow_copy_constructible<FunctionType>::value)
: ScopeGuardImpl(
asConst(fn),
makeFailsafe(
std::is_nothrow_copy_constructible<FunctionType>{},
&fn)) {
}
explicit ScopeGuardImpl(const FunctionType& fn) noexcept(
std::is_nothrow_copy_constructible<FunctionType>::value)
: ScopeGuardImpl(
fn,
makeFailsafe(
std::is_nothrow_copy_constructible<FunctionType>{},
&fn)) {
}
explicit ScopeGuardImpl(FunctionType&& fn) noexcept(
std::is_nothrow_move_constructible<FunctionType>::value)
: ScopeGuardImpl(
std::move_if_noexcept(fn),
makeFailsafe(
std::is_nothrow_move_constructible<FunctionType>{},
&fn)) {
}
ScopeGuardImpl(ScopeGuardImpl&& other) noexcept(
std::is_nothrow_move_constructible<FunctionType>::value)
: function_(std::move_if_noexcept(other.function_)) {
dismissed_ = std::exchange(other.dismissed_, true);
}
~ScopeGuardImpl() noexcept(InvokeNoexcept) {
if (!dismissed_) {
execute();
}
}
private:
static ScopeGuardImplBase makeFailsafe(std::true_type,
const void*) noexcept {
return makeEmptyScopeGuard();
}
template <typename Fn>
static auto makeFailsafe(std::false_type, Fn* fn) noexcept
-> ScopeGuardImpl<decltype(std::ref(*fn)), InvokeNoexcept> {
return ScopeGuardImpl<decltype(std::ref(*fn)), InvokeNoexcept>{
std::ref(*fn)};
}
template <typename Fn>
explicit ScopeGuardImpl(Fn&& fn, ScopeGuardImplBase&& failsafe)
: ScopeGuardImplBase{}, function_(std::forward<Fn>(fn)) {
failsafe.dismiss();
}
void* operator new(std::size_t) = delete;
void execute() noexcept(InvokeNoexcept) {
if (InvokeNoexcept) {
using R = decltype(function_());
auto catcher = []() -> R { warnAboutToCrash(), std::terminate(); };
catch_exception(function_, catcher);
} else {
function_();
}
}
FunctionType function_;
};
template <typename F, bool INE>
using ScopeGuardImplDecay = ScopeGuardImpl<typename std::decay<F>::type, INE>;
} // namespace detail
// # 181 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 3 4
template <typename F>
[[nodiscard]] detail::ScopeGuardImplDecay<F, true> makeGuard(F&& f) noexcept(
noexcept(detail::ScopeGuardImplDecay<F, true>(static_cast<F&&>(f)))) {
return detail::ScopeGuardImplDecay<F, true>(static_cast<F&&>(f));
}
namespace detail {
// # 204 "tlm/deps/folly.exploded/include/folly/ScopeGuard.h" 3 4
template <typename FunctionType, bool ExecuteOnException>
class ScopeGuardForNewException {
public:
explicit ScopeGuardForNewException(const FunctionType& fn) : guard_(fn) {
}
explicit ScopeGuardForNewException(FunctionType&& fn)
: guard_(std::move(fn)) {
}
ScopeGuardForNewException(ScopeGuardForNewException&& other) = default;
~ScopeGuardForNewException() noexcept(ExecuteOnException) {
if (ExecuteOnException != (exceptionCounter_ < uncaught_exceptions())) {
guard_.dismiss();
}
}
private:
void* operator new(std::size_t) = delete;
void operator delete(void*) = delete;
ScopeGuardImpl<FunctionType, ExecuteOnException> guard_;
int exceptionCounter_{uncaught_exceptions()};
};
enum class ScopeGuardOnFail {};
template <typename FunctionType>
ScopeGuardForNewException<typename std::decay<FunctionType>::type, true>
operator+(detail::ScopeGuardOnFail, FunctionType&& fn) {
return ScopeGuardForNewException<typename std::decay<FunctionType>::type,
true>(std::forward<FunctionType>(fn));
}
enum class ScopeGuardOnSuccess {};
template <typename FunctionType>
ScopeGuardForNewException<typename std::decay<FunctionType>::type, false>
operator+(ScopeGuardOnSuccess, FunctionType&& fn) {
return ScopeGuardForNewException<typename std::decay<FunctionType>::type,
false>(std::forward<FunctionType>(fn));
}
enum class ScopeGuardOnExit {};
template <typename FunctionType>
ScopeGuardImpl<typename std::decay<FunctionType>::type, true> operator+(
detail::ScopeGuardOnExit, FunctionType&& fn) {
return ScopeGuardImpl<typename std::decay<FunctionType>::type, true>(
std::forward<FunctionType>(fn));
}
} // namespace detail
} // namespace folly
// # 51 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 1 3 4
// # 19 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
// # 29 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 2 3
// 4 # 31 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 3
// 4 # 1 "tlm/deps/folly.exploded/include/folly/Indestructible.h" 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/Indestructible.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/Indestructible.h" 2 3 4
namespace folly {
// # 60 "tlm/deps/folly.exploded/include/folly/Indestructible.h" 3 4
template <typename T>
class Indestructible final {
public:
template <typename S = T, typename = decltype(S())>
constexpr Indestructible() noexcept(noexcept(T())) {
}
// # 81 "tlm/deps/folly.exploded/include/folly/Indestructible.h" 3 4
template <typename U = T,
std::enable_if_t<std::is_constructible<T, U&&>::value>* = nullptr,
std::enable_if_t<!std::is_same<Indestructible<T>,
remove_cvref_t<U>>::value>* =
nullptr,
std::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr>
explicit constexpr Indestructible(U&& u) noexcept(
noexcept(T(std::declval<U>())))
: storage_(std::forward<U>(u)) {
}
template <typename U = T,
std::enable_if_t<std::is_constructible<T, U&&>::value>* = nullptr,
std::enable_if_t<!std::is_same<Indestructible<T>,
remove_cvref_t<U>>::value>* =
nullptr,
std::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr>
constexpr Indestructible(U&& u) noexcept(noexcept(T(std::declval<U>())))
: storage_(std::forward<U>(u)) {
}
template <typename... Args, typename = decltype(T(std::declval<Args>()...))>
explicit constexpr Indestructible(Args&&... args) noexcept(
noexcept(T(std::declval<Args>()...)))
: storage_(std::forward<Args>(args)...) {
}
template <typename U,
typename... Args,
typename = decltype(T(std::declval<std::initializer_list<U>&>(),
std::declval<Args>()...))>
explicit constexpr Indestructible(
std::initializer_list<U> il,
Args... args) noexcept(noexcept(T(std::
declval<std::initializer_list<
U>&>(),
std::declval<Args>()...)))
: storage_(il, std::forward<Args>(args)...) {
}
~Indestructible() = default;
Indestructible(Indestructible const&) = delete;
Indestructible& operator=(Indestructible const&) = delete;
Indestructible(Indestructible&& other) noexcept(
noexcept(T(std::declval<T>())))
: storage_(std::move(other.storage_.value)) {
other.erased_ = true;
}
Indestructible& operator=(Indestructible&& other) noexcept(
noexcept(T(std::declval<T>()))) {
storage_.value = std::move(other.storage_.value);
other.erased_ = true;
}
T* get() noexcept {
check();
return &storage_.value;
}
T const* get() const noexcept {
check();
return &storage_.value;
}
T& operator*() noexcept {
return *get();
}
T const& operator*() const noexcept {
return *get();
}
T* operator->() noexcept {
return get();
}
T const* operator->() const noexcept {
return get();
}
private:
void check() const noexcept {
(static_cast<bool>(!erased_)
? void(0)
: __assert_fail("!erased_",
"tlm/deps/folly.exploded/include/folly/"
"Indestructible.h",
157,
__extension__ __PRETTY_FUNCTION__));
}
union Storage {
T value;
template <typename S = T, typename = decltype(S())>
constexpr Storage() noexcept(noexcept(T())) : value() {
}
template <typename... Args,
typename = decltype(T(std::declval<Args>()...))>
explicit constexpr Storage(Args&&... args) noexcept(
noexcept(T(std::declval<Args>()...)))
: value(std::forward<Args>(args)...) {
}
~Storage() {
}
};
Storage storage_{};
bool erased_{false};
};
} // namespace folly
// # 32 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 2 3
// 4
// # 1 "tlm/deps/folly.exploded/include/folly/Memory.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
// # 33 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/control/expr_iif.hpp"
// 1 3 4 # 15
// "tlm/deps/boost.exploded/include/boost/preprocessor/control/expr_iif.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/config/config.hpp" 1
// 3 4 # 16
// "tlm/deps/boost.exploded/include/boost/preprocessor/control/expr_iif.hpp" 2 3
// 4 # 23 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/is_empty_variadic.hpp"
// 1 3 4 # 19
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/is_empty_variadic.hpp"
// 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/punctuation/is_begin_parens.hpp"
// 1 3 4 # 19
// "tlm/deps/boost.exploded/include/boost/preprocessor/punctuation/is_begin_parens.hpp"
// 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/punctuation/detail/is_begin_parens.hpp"
// 1 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/punctuation/is_begin_parens.hpp"
// 2 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/is_empty_variadic.hpp"
// 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/detail/is_empty.hpp"
// 1 3 4 # 21
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/is_empty_variadic.hpp"
// 2 3 4 # 24 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each.hpp" 1
// 3 4 # 18
// "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each.hpp" 3 4 #
// 1 "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp" 1
// 3 4 # 17
// "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/arithmetic/inc.hpp" 1
// 3 4 # 18
// "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp" 2 3
// 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/list/adt.hpp" 1 3 4
// # 18 "tlm/deps/boost.exploded/include/boost/preprocessor/list/adt.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/detail/is_binary.hpp"
// 1 3 4 # 16
// "tlm/deps/boost.exploded/include/boost/preprocessor/detail/is_binary.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/detail/check.hpp" 1 3
// 4 # 15 "tlm/deps/boost.exploded/include/boost/preprocessor/detail/check.hpp"
// 3 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/cat.hpp" 1 3 4 #
// 16 "tlm/deps/boost.exploded/include/boost/preprocessor/detail/check.hpp" 2 3
// 4 # 17
// "tlm/deps/boost.exploded/include/boost/preprocessor/detail/is_binary.hpp" 2 3
// 4 # 19 "tlm/deps/boost.exploded/include/boost/preprocessor/list/adt.hpp" 2 3
// 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/logical/compl.hpp"
// 1 3 4 # 20 "tlm/deps/boost.exploded/include/boost/preprocessor/list/adt.hpp"
// 2 3 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/eat.hpp"
// 1 3 4 # 21 "tlm/deps/boost.exploded/include/boost/preprocessor/list/adt.hpp"
// 2 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp" 2 3
// 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp"
// 1 3 4 # 18
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/debug/error.hpp" 1 3
// 4 # 19
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 2 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/empty.hpp"
// 1 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 2 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/logical/bool.hpp" 1 3
// 4 # 21
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 2 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/detail/auto_rec.hpp"
// 1 3 4 # 21
// "tlm/deps/boost.exploded/include/boost/preprocessor/detail/auto_rec.hpp" 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/control/iif.hpp" 1 3
// 4 # 22
// "tlm/deps/boost.exploded/include/boost/preprocessor/detail/auto_rec.hpp" 2 3
// 4 # 22
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 2 3 4
// # 44 "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp"
// 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/detail/for.hpp"
// 1 3 4 # 45
// "tlm/deps/boost.exploded/include/boost/preprocessor/repetition/for.hpp" 2 3 4
// # 21 "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp"
// 2 3 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp"
// 1 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp" 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/expand.hpp" 1
// 3 4 # 21 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp"
// 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/overload.hpp"
// 1 3 4 # 17
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/overload.hpp"
// 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/variadic/size.hpp" 1 3 4
// # 18
// "tlm/deps/boost.exploded/include/boost/preprocessor/facilities/overload.hpp"
// 2 3 4 # 22
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp" 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/rem.hpp" 1 3 4 # 20
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/rem.hpp" 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/detail/is_single_return.hpp"
// 1 3 4 # 21 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/rem.hpp"
// 2 3 4 # 23
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp" 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/variadic/elem.hpp" 1 3 4
// # 24 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/elem.hpp" 2 3
// 4 # 22
// "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each_i.hpp" 2 3
// 4 # 19 "tlm/deps/boost.exploded/include/boost/preprocessor/list/for_each.hpp"
// 2 3 4 # 25 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4
// # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/logical/not.hpp" 1 3
// 4 # 26 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4 # 1
// "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/to_list.hpp" 1 3 4
// # 21 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/to_list.hpp" 3
// 4 # 1 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/size.hpp" 1 3
// 4 # 22 "tlm/deps/boost.exploded/include/boost/preprocessor/tuple/to_list.hpp"
// 2 3 4 # 27 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/CustomizationPoint.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/CustomizationPoint.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/StaticConst.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/StaticConst.h" 3 4
namespace folly {
template <typename T>
struct StaticConst {
static constexpr T value{};
};
template <typename T>
constexpr T StaticConst<T>::value;
} // namespace folly
// # 23 "tlm/deps/folly.exploded/include/folly/lang/CustomizationPoint.h" 2 3 4
// # 50 "tlm/deps/folly.exploded/include/folly/lang/CustomizationPoint.h" 3 4
namespace folly {
// # 71 "tlm/deps/folly.exploded/include/folly/lang/CustomizationPoint.h" 3 4
template <const auto& Tag>
using cpo_t = std::decay_t<decltype(Tag)>;
} // namespace folly
// # 34 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 2 3 4
// # 52 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
namespace folly {
using std::invoke;
}
// # 82 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
namespace folly {
using std::invoke_result;
using std::invoke_result_t;
using std::is_invocable;
using std::is_invocable_r;
using std::is_invocable_r_v;
using std::is_invocable_v;
using std::is_nothrow_invocable;
using std::is_nothrow_invocable_r;
using std::is_nothrow_invocable_r_v;
using std::is_nothrow_invocable_v;
} // namespace folly
// # 204 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
namespace folly {
namespace detail {
struct invoke_private_overload;
template <bool, typename Invoke>
struct invoke_traits_base_ {};
template <typename Invoke>
struct invoke_traits_base_<false, Invoke> {};
template <typename Invoke>
struct invoke_traits_base_<true, Invoke> {
inline static constexpr Invoke invoke{};
};
template <typename Invoke>
using invoke_traits_base =
invoke_traits_base_<is_constexpr_default_constructible_v<Invoke>,
Invoke>;
} // namespace detail
// # 252 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
template <typename Invoke>
struct invoke_traits : detail::invoke_traits_base<Invoke> {
public:
using invoke_type = Invoke;
template <typename... Args>
struct invoke_result : folly::invoke_result<Invoke, Args...> {};
template <typename... Args>
using invoke_result_t = folly::invoke_result_t<Invoke, Args...>;
template <typename... Args>
struct is_invocable : folly::is_invocable<Invoke, Args...> {};
template <typename... Args>
inline static constexpr bool is_invocable_v = is_invocable<Args...>::value;
template <typename R, typename... Args>
struct is_invocable_r : folly::is_invocable_r<R, Invoke, Args...> {};
template <typename R, typename... Args>
inline static constexpr bool is_invocable_r_v =
is_invocable_r<R, Args...>::value;
template <typename... Args>
struct is_nothrow_invocable : folly::is_nothrow_invocable<Invoke, Args...> {
};
template <typename... Args>
inline static constexpr bool is_nothrow_invocable_v =
is_nothrow_invocable<Args...>::value;
template <typename R, typename... Args>
struct is_nothrow_invocable_r
: folly::is_nothrow_invocable_r<R, Invoke, Args...> {};
template <typename R, typename... Args>
inline static constexpr bool is_nothrow_invocable_r_v =
is_nothrow_invocable_r<R, Args...>::value;
};
} // namespace folly
// # 484 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
namespace folly {
namespace detail_tag_invoke_fn {
void tag_invoke();
struct tag_invoke_fn {
template <typename Tag, typename... Args>
constexpr auto operator()(Tag tag, Args&&... args) const
noexcept(noexcept(tag_invoke(static_cast<Tag&&>(tag),
static_cast<Args&&>(args)...)))
-> decltype(tag_invoke(static_cast<Tag&&>(tag),
static_cast<Args&&>(args)...)) {
return tag_invoke(static_cast<Tag&&>(tag),
static_cast<Args&&>(args)...);
}
};
// # 509 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
template <typename Tag, typename... Args>
using tag_invoke_result_t =
decltype(tag_invoke(static_cast<Tag && (*)() noexcept>(nullptr)(),
static_cast<Args && (*)() noexcept>(nullptr)()...));
template <typename Tag, typename... Args>
auto try_tag_invoke(int) noexcept(
noexcept(tag_invoke(static_cast<Tag && (*)() noexcept>(nullptr)(),
static_cast<Args && (*)() noexcept>(nullptr)()...)))
-> decltype(static_cast<void>(tag_invoke(
static_cast<Tag && (*)() noexcept>(nullptr)(),
static_cast<Args && (*)() noexcept>(nullptr)()...)),
std::true_type{});
template <typename Tag, typename... Args>
std::false_type try_tag_invoke(...) noexcept(false);
template <template <typename...> class T, typename... Args>
struct defer {
using type = T<Args...>;
};
struct empty {};
} // namespace detail_tag_invoke_fn
// # 564 "tlm/deps/folly.exploded/include/folly/functional/Invoke.h" 3 4
namespace folly_cpo__ {
inline constexpr detail_tag_invoke_fn::tag_invoke_fn tag_invoke{};
}
using namespace folly_cpo__;
template <typename Tag, typename... Args>
inline constexpr bool is_tag_invocable_v =
decltype(detail_tag_invoke_fn::try_tag_invoke<Tag, Args...>(0))::value;
template <typename Tag, typename... Args>
struct is_tag_invocable : bool_constant<is_tag_invocable_v<Tag, Args...>> {};
template <typename Tag, typename... Args>
inline constexpr bool is_nothrow_tag_invocable_v =
noexcept(detail_tag_invoke_fn::try_tag_invoke<Tag, Args...>(0));
template <typename Tag, typename... Args>
struct is_nothrow_tag_invocable
: bool_constant<is_nothrow_tag_invocable_v<Tag, Args...>> {};
template <typename R, typename Tag, typename... Args>
using is_tag_invocable_r =
folly::is_invocable_r<R, decltype(folly::tag_invoke), Tag, Args...>;
template <typename R, typename Tag, typename... Args>
inline constexpr bool is_tag_invocable_r_v =
is_tag_invocable_r<R, decltype(folly::tag_invoke), Tag, Args...>::value;
template <typename R, typename Tag, typename... Args>
using is_nothrow_tag_invocable_r = folly::
is_nothrow_invocable_r<R, decltype(folly::tag_invoke), Tag, Args...>;
template <typename R, typename Tag, typename... Args>
inline constexpr bool is_nothrow_tag_invocable_r_v =
is_nothrow_tag_invocable_r<R, Tag, Args...>::value;
using detail_tag_invoke_fn::tag_invoke_result_t;
template <typename Tag, typename... Args>
struct tag_invoke_result
: conditional_t<
is_tag_invocable_v<Tag, Args...>,
detail_tag_invoke_fn::defer<tag_invoke_result_t, Tag, Args...>,
detail_tag_invoke_fn::empty> {};
} // namespace folly
// # 34 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 3 4
namespace folly {
// # 37 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 3 4
constexpr bool has_extended_alignment =
kIsLinux && sizeof(void*) >= sizeof(std::uint64_t);
namespace detail {
template <typename... Ts>
struct max_align_t_ {
static constexpr std::size_t value() {
std::size_t const values[] = {0u, alignof(Ts)...};
std::size_t r = 0u;
for (auto const v : values) {
r = r < v ? v : r;
}
return r;
}
};
using max_align_v_ = max_align_t_<long double,
double,
float,
long long int,
long int,
int,
short int,
bool,
char,
char16_t,
char32_t,
wchar_t,
void*,
std::max_align_t>;
} // namespace detail
// # 105 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 3 4
constexpr std::size_t max_align_v = detail::max_align_v_::value();
struct alignas(max_align_v) max_align_t {};
// # 122 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 3 4
constexpr std::size_t hardware_destructive_interference_size =
(kIsArchArm || kIsArchS390X) ? 64 : 128;
static_assert(hardware_destructive_interference_size >= max_align_v, "math?");
// # 133 "tlm/deps/folly.exploded/include/folly/lang/Align.h" 3 4
constexpr std::size_t hardware_constructive_interference_size = 64;
static_assert(hardware_constructive_interference_size >= max_align_v, "math?");
constexpr std::size_t cacheline_align_v =
has_extended_alignment ? hardware_constructive_interference_size
: max_align_v;
struct alignas(cacheline_align_v) cacheline_align_t {};
} // namespace folly
// # 35 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 1 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Malloc.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Malloc.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/portability/Malloc.h" 2 3 4
// # 39 "tlm/deps/folly.exploded/include/folly/portability/Malloc.h" 3 4
// # 40 "tlm/deps/folly.exploded/include/folly/portability/Malloc.h" 2 3 4
// # 25 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 2 3 4
// # 43 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/memory/detail/MallocImpl.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/memory/detail/MallocImpl.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/memory/detail/MallocImpl.h" 2 3 4
extern "C" {
void* mallocx(size_t, int) __attribute__((__nothrow__, __weak__));
void* rallocx(void*, size_t, int) __attribute__((__nothrow__, __weak__));
size_t xallocx(void*, size_t, size_t, int)
__attribute__((__nothrow__, __weak__));
size_t sallocx(const void*, int) __attribute__((__nothrow__, __weak__));
void dallocx(void*, int) __attribute__((__nothrow__, __weak__));
void sdallocx(void*, size_t, int) __attribute__((__nothrow__, __weak__));
size_t nallocx(size_t, int) __attribute__((__nothrow__, __weak__));
int mallctl(const char*, void*, size_t*, void*, size_t)
__attribute__((__nothrow__, __weak__));
int mallctlnametomib(const char*, size_t*, size_t*)
__attribute__((__nothrow__, __weak__));
int mallctlbymib(const size_t*, size_t, void*, size_t*, void*, size_t)
__attribute__((__nothrow__, __weak__));
bool MallocExtension_Internal_GetNumericProperty(const char*, size_t, size_t*)
__attribute__((__weak__));
// # 97 "tlm/deps/folly.exploded/include/folly/memory/detail/MallocImpl.h" 3 4
}
// # 44 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 2 3 4
// # 46 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 2 3 4
// # 49 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 2 3 4
// # 50 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 2 3 4
namespace folly {
// # 79 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
__attribute__((__noinline__)) inline bool usingJEMalloc() noexcept {
// # 88 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
static const bool result = []() noexcept {
if (mallocx == nullptr || rallocx == nullptr || xallocx == nullptr ||
sallocx == nullptr || dallocx == nullptr || sdallocx == nullptr ||
nallocx == nullptr || mallctl == nullptr ||
mallctlnametomib == nullptr || mallctlbymib == nullptr) {
return false;
}
volatile uint64_t* counter;
size_t counterLen = sizeof(uint64_t*);
if (mallctl("thread.allocatedp",
static_cast<void*>(&counter),
&counterLen,
nullptr,
0) != 0) {
return false;
}
if (counterLen != sizeof(uint64_t*)) {
return false;
}
uint64_t origAllocated = *counter;
static void* volatile ptr = malloc(1);
if (!ptr) {
return false;
}
free(ptr);
return (origAllocated != *counter);
}();
return result;
}
inline bool getTCMallocNumericProperty(const char* name, size_t* out) noexcept {
return MallocExtension_Internal_GetNumericProperty(name, strlen(name), out);
}
// # 148 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
__attribute__((__noinline__)) inline bool usingTCMalloc() noexcept {
static const bool result = []() noexcept {
if (MallocExtension_Internal_GetNumericProperty == nullptr ||
sdallocx == nullptr || nallocx == nullptr) {
return false;
}
static const char kAllocBytes[] = "generic.current_allocated_bytes";
size_t before_bytes = 0;
getTCMallocNumericProperty(kAllocBytes, &before_bytes);
static void* volatile ptr = malloc(1);
if (!ptr) {
return false;
}
size_t after_bytes = 0;
getTCMallocNumericProperty(kAllocBytes, &after_bytes);
free(ptr);
return (before_bytes != after_bytes);
}();
return result;
}
__attribute__((__noinline__)) inline bool canSdallocx() noexcept {
static bool rv = usingJEMalloc() || usingTCMalloc();
return rv;
}
__attribute__((__noinline__)) inline bool canNallocx() noexcept {
static bool rv = usingJEMalloc() || usingTCMalloc();
return rv;
}
inline size_t goodMallocSize(size_t minSize) noexcept {
if (minSize == 0) {
return 0;
}
if (!canNallocx()) {
return minSize;
}
auto rv = nallocx(minSize, 0);
return rv ? rv : minSize;
}
static const size_t jemallocMinInPlaceExpandable = 4096;
inline void* checkedMalloc(size_t size) {
void* p = malloc(size);
if (!p) {
throw_exception<std::bad_alloc>();
}
return p;
}
inline void* checkedCalloc(size_t n, size_t size) {
void* p = calloc(n, size);
if (!p) {
throw_exception<std::bad_alloc>();
}
return p;
}
inline void* checkedRealloc(void* ptr, size_t size) {
void* p = realloc(ptr, size);
if (!p) {
throw_exception<std::bad_alloc>();
}
return p;
}
inline void sizedFree(void* ptr, size_t size) {
if (canSdallocx()) {
sdallocx(ptr, size, 0);
} else {
free(ptr);
}
}
// # 259 "tlm/deps/folly.exploded/include/folly/memory/Malloc.h" 3 4
__attribute__((__returns_nonnull__, __malloc__))
__attribute__((__noinline__)) inline void*
smartRealloc(void* p,
const size_t currentSize,
const size_t currentCapacity,
const size_t newCapacity) {
(static_cast<bool>(p)
? void(0)
: __assert_fail(
"p",
"tlm/deps/folly.exploded/include/folly/memory/Malloc.h",
264,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(currentSize <= currentCapacity &&
currentCapacity < newCapacity)
? void(0)
: __assert_fail(
"currentSize <= currentCapacity && currentCapacity < "
"newCapacity",
"tlm/deps/folly.exploded/include/folly/memory/Malloc.h",
265,
__extension__ __PRETTY_FUNCTION__));
auto const slack = currentCapacity - currentSize;
if (slack * 2 > currentSize) {
auto const result = checkedMalloc(newCapacity);
std::memcpy(result, p, currentSize);
free(p);
return result;
}
return checkedRealloc(p, newCapacity);
}
} // namespace folly
// # 37 "tlm/deps/folly.exploded/include/folly/Memory.h" 2 3 4
namespace folly {
inline void* allocateBytes(size_t n) {
return ::operator new(n);
}
inline void deallocateBytes(void* p, size_t n) {
return ::operator delete(p, n);
}
// # 64 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
inline void* aligned_malloc(size_t size, size_t align) {
void* ptr = nullptr;
int rc = posix_memalign(&ptr, align, size);
return rc == 0 ? ((*__errno_location()) = 0, ptr)
: ((*__errno_location()) = rc, nullptr);
}
inline void aligned_free(void* aligned_ptr) {
free(aligned_ptr);
}
// # 97 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
namespace detail {
template <typename Alloc, size_t kAlign, bool kAllocate>
void rawOverAlignedImpl(Alloc const& alloc, size_t n, void*& raw) {
static_assert((kAlign & (kAlign - 1)) == 0, "Align must be a power of 2");
using AllocTraits = std::allocator_traits<Alloc>;
using T = typename AllocTraits::value_type;
constexpr bool kCanBypass = std::is_same<Alloc, std::allocator<T>>::value;
constexpr size_t kBaseAlign = constexpr_min(kAlign, alignof(max_align_t));
using BaseType = std::aligned_storage_t<kBaseAlign, kBaseAlign>;
using BaseAllocTraits =
typename AllocTraits::template rebind_traits<BaseType>;
using BaseAlloc = typename BaseAllocTraits::allocator_type;
static_assert(
sizeof(BaseType) == kBaseAlign && alignof(BaseType) == kBaseAlign,
"");
if (kCanBypass && kAlign == kBaseAlign) {
if (kAllocate) {
raw = ::operator new(n * sizeof(T));
} else {
::operator delete(raw, n * sizeof(T));
}
return;
}
if (kCanBypass && kAlign > kBaseAlign) {
if (kAllocate) {
raw = aligned_malloc(n * sizeof(T), kAlign);
} else {
aligned_free(raw);
}
return;
}
BaseAlloc a(alloc);
size_t quanta = (n * sizeof(T) + kBaseAlign - 1) / sizeof(BaseType);
if (kAlign <= kBaseAlign) {
if (kAllocate) {
raw = static_cast<void*>(
std::addressof(*BaseAllocTraits::allocate(a, quanta)));
} else {
BaseAllocTraits::deallocate(
a,
std::pointer_traits<typename BaseAllocTraits::pointer>::
pointer_to(*static_cast<BaseType*>(raw)),
quanta);
}
return;
}
// # 173 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
if (kAllocate) {
char* base = reinterpret_cast<char*>(
std::addressof(*BaseAllocTraits::allocate(
a, quanta + kAlign / sizeof(BaseType))));
size_t byteDelta =
kAlign - (reinterpret_cast<uintptr_t>(base) & (kAlign - 1));
raw = static_cast<void*>(base + byteDelta);
static_cast<size_t*>(raw)[-1] = byteDelta;
} else {
size_t byteDelta = static_cast<size_t*>(raw)[-1];
char* base = static_cast<char*>(raw) - byteDelta;
BaseAllocTraits::deallocate(
a,
std::pointer_traits<typename BaseAllocTraits::pointer>::
pointer_to(*reinterpret_cast<BaseType*>(base)),
quanta + kAlign / sizeof(BaseType));
}
}
} // namespace detail
template <typename Alloc,
size_t kAlign =
alignof(typename std::allocator_traits<Alloc>::value_type)>
typename std::allocator_traits<Alloc>::pointer allocateOverAligned(
Alloc const& alloc, size_t n) {
void* raw = nullptr;
detail::rawOverAlignedImpl<Alloc, kAlign, true>(alloc, n, raw);
return std::pointer_traits<typename std::allocator_traits<Alloc>::pointer>::
pointer_to(*static_cast<
typename std::allocator_traits<Alloc>::value_type*>(
raw));
}
template <typename Alloc,
size_t kAlign =
alignof(typename std::allocator_traits<Alloc>::value_type)>
void deallocateOverAligned(Alloc const& alloc,
typename std::allocator_traits<Alloc>::pointer ptr,
size_t n) {
void* raw = static_cast<void*>(std::addressof(*ptr));
detail::rawOverAlignedImpl<Alloc, kAlign, false>(alloc, n, raw);
}
template <typename Alloc,
size_t kAlign =
alignof(typename std::allocator_traits<Alloc>::value_type)>
size_t allocationBytesForOverAligned(size_t n) {
static_assert((kAlign & (kAlign - 1)) == 0, "Align must be a power of 2");
using AllocTraits = std::allocator_traits<Alloc>;
using T = typename AllocTraits::value_type;
constexpr size_t kBaseAlign = constexpr_min(kAlign, alignof(max_align_t));
if (kAlign > kBaseAlign && std::is_same<Alloc, std::allocator<T>>::value) {
return n * sizeof(T);
} else {
size_t quanta = (n * sizeof(T) + kBaseAlign - 1) / kBaseAlign;
if (kAlign > kBaseAlign) {
quanta += kAlign / kBaseAlign;
}
return quanta * kBaseAlign;
}
}
// # 255 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
using std::make_unique;
// # 299 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T, void (*f)(T*)>
struct static_function_deleter {
void operator()(T* t) const {
f(t);
}
};
// # 324 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T, typename D>
std::shared_ptr<T> to_shared_ptr(std::unique_ptr<T, D>&& ptr) {
return std::shared_ptr<T>(std::move(ptr));
}
// # 347 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T>
std::weak_ptr<T> to_weak_ptr(const std::shared_ptr<T>& ptr) {
return std::weak_ptr<T>(ptr);
}
// # 359 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T>
std::unique_ptr<remove_cvref_t<T>> copy_to_unique_ptr(T&& t) {
return make_unique<remove_cvref_t<T>>(static_cast<T&&>(t));
}
// # 371 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T>
std::shared_ptr<remove_cvref_t<T>> copy_to_shared_ptr(T&& t) {
return std::make_shared<remove_cvref_t<T>>(static_cast<T&&>(t));
}
template <typename T>
class SysAllocator {
private:
using Self = SysAllocator<T>;
public:
using value_type = T;
constexpr SysAllocator() = default;
constexpr SysAllocator(SysAllocator const&) = default;
template <typename U, std::enable_if_t<!std::is_same<U, T>::value, int> = 0>
constexpr SysAllocator(SysAllocator<U> const&) noexcept {
}
T* allocate(size_t count) {
auto const p = std::malloc(sizeof(T) * count);
if (!p) {
throw_exception<std::bad_alloc>();
}
return static_cast<T*>(p);
}
void deallocate(T* p, size_t count) {
sizedFree(p, count * sizeof(T));
}
friend bool operator==(Self const&, Self const&) noexcept {
return true;
}
friend bool operator!=(Self const&, Self const&) noexcept {
return false;
}
};
class DefaultAlign {
private:
using Self = DefaultAlign;
std::size_t align_;
public:
explicit DefaultAlign(std::size_t align) noexcept : align_(align) {
(static_cast<bool>(!(align_ < sizeof(void*)) &&
bool("bad align: too small"))
? void(0)
: __assert_fail(
"!(align_ < sizeof(void*)) && bool(\"bad align: too "
"small\")",
"tlm/deps/folly.exploded/include/folly/Memory.h",
423,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(!(align_ & (align_ - 1)) &&
bool("bad align: not power-of-two"))
? void(0)
: __assert_fail(
"!(align_ & (align_ - 1)) && bool(\"bad align: not "
"power-of-two\")",
"tlm/deps/folly.exploded/include/folly/Memory.h",
424,
__extension__ __PRETTY_FUNCTION__));
}
std::size_t operator()() const noexcept {
return align_;
}
friend bool operator==(Self const& a, Self const& b) noexcept {
return a.align_ == b.align_;
}
friend bool operator!=(Self const& a, Self const& b) noexcept {
return a.align_ != b.align_;
}
};
template <std::size_t Align>
class FixedAlign {
private:
static_assert(!(Align < sizeof(void*)), "bad align: too small");
static_assert(!(Align & (Align - 1)), "bad align: not power-of-two");
using Self = FixedAlign<Align>;
public:
constexpr std::size_t operator()() const noexcept {
return Align;
}
friend bool operator==(Self const&, Self const&) noexcept {
return true;
}
friend bool operator!=(Self const&, Self const&) noexcept {
return false;
}
};
// # 474 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T, typename Align = DefaultAlign>
class AlignedSysAllocator : private Align {
private:
using Self = AlignedSysAllocator<T, Align>;
template <typename, typename>
friend class AlignedSysAllocator;
constexpr Align const& align() const {
return *this;
}
public:
static_assert(std::is_nothrow_copy_constructible<Align>::value, "");
static_assert(is_nothrow_invocable_r_v<std::size_t, Align>, "");
using value_type = T;
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
using Align::Align;
template <
typename S = Align,
std::enable_if_t<std::is_default_constructible<S>::value, int> = 0>
constexpr AlignedSysAllocator() noexcept(noexcept(Align())) : Align() {
}
constexpr AlignedSysAllocator(AlignedSysAllocator const&) = default;
template <typename U, std::enable_if_t<!std::is_same<U, T>::value, int> = 0>
constexpr AlignedSysAllocator(
AlignedSysAllocator<U, Align> const& other) noexcept
: Align(other.align()) {
}
T* allocate(size_t count) {
auto const a = align()() < alignof(T) ? alignof(T) : align()();
auto const p = aligned_malloc(sizeof(T) * count, a);
if (!p) {
if ((__builtin_expect(((*__errno_location()) != 12), 0))) {
std::terminate();
}
throw_exception<std::bad_alloc>();
}
return static_cast<T*>(p);
}
void deallocate(T* p, size_t) {
aligned_free(p);
}
friend bool operator==(Self const& a, Self const& b) noexcept {
return a.align() == b.align();
}
friend bool operator!=(Self const& a, Self const& b) noexcept {
return a.align() != b.align();
}
};
// # 545 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename T, class Inner, bool FallbackToStdAlloc = false>
class CxxAllocatorAdaptor : private std::allocator<T> {
private:
using Self = CxxAllocatorAdaptor<T, Inner, FallbackToStdAlloc>;
template <typename U, typename UInner, bool UFallback>
friend class CxxAllocatorAdaptor;
Inner* inner_ = nullptr;
public:
using value_type = T;
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
template <bool X = FallbackToStdAlloc, std::enable_if_t<X, int> = 0>
constexpr explicit CxxAllocatorAdaptor() {
}
constexpr explicit CxxAllocatorAdaptor(Inner& ref) : inner_(&ref) {
}
constexpr CxxAllocatorAdaptor(CxxAllocatorAdaptor const&) = default;
template <typename U, std::enable_if_t<!std::is_same<U, T>::value, int> = 0>
constexpr CxxAllocatorAdaptor(
CxxAllocatorAdaptor<U, Inner, FallbackToStdAlloc> const& other)
: inner_(other.inner_) {
}
T* allocate(std::size_t n) {
if (FallbackToStdAlloc && inner_ == nullptr) {
return std::allocator<T>::allocate(n);
}
return static_cast<T*>(inner_->allocate(sizeof(T) * n));
}
void deallocate(T* p, std::size_t n) {
if (inner_ != nullptr) {
inner_->deallocate(p, sizeof(T) * n);
} else {
(static_cast<bool>(FallbackToStdAlloc)
? void(0)
: __assert_fail(
"FallbackToStdAlloc",
"tlm/deps/folly.exploded/include/folly/Memory.h",
585,
__extension__ __PRETTY_FUNCTION__));
std::allocator<T>::deallocate(p, n);
}
}
friend bool operator==(Self const& a, Self const& b) noexcept {
return a.inner_ == b.inner_;
}
friend bool operator!=(Self const& a, Self const& b) noexcept {
return a.inner_ != b.inner_;
}
template <typename U>
struct rebind {
using other = CxxAllocatorAdaptor<U, Inner, FallbackToStdAlloc>;
};
};
// # 611 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename Alloc>
class allocator_delete : private std::remove_reference<Alloc>::type {
private:
using allocator_type = typename std::remove_reference<Alloc>::type;
using allocator_traits = std::allocator_traits<allocator_type>;
using value_type = typename allocator_traits::value_type;
using pointer = typename allocator_traits::pointer;
public:
allocator_delete() = default;
allocator_delete(allocator_delete const&) = default;
allocator_delete(allocator_delete&&) = default;
allocator_delete& operator=(allocator_delete const&) = default;
allocator_delete& operator=(allocator_delete&&) = default;
explicit allocator_delete(const allocator_type& alloc)
: allocator_type(alloc) {
}
explicit allocator_delete(allocator_type&& alloc)
: allocator_type(std::move(alloc)) {
}
template <typename U>
allocator_delete(const allocator_delete<U>& other)
: allocator_type(other.get_allocator()) {
}
allocator_type const& get_allocator() const {
return *this;
}
void operator()(pointer p) const {
auto alloc = get_allocator();
allocator_traits::destroy(alloc, p);
allocator_traits::deallocate(alloc, p, 1);
}
};
template <typename T, typename Alloc, typename... Args>
std::unique_ptr<T, allocator_delete<Alloc>> allocate_unique(Alloc const& alloc,
Args&&... args) {
using traits = std::allocator_traits<Alloc>;
struct DeferCondDeallocate {
bool& cond;
Alloc& copy;
T* p;
~DeferCondDeallocate() {
if ((__builtin_expect((!cond), 0))) {
traits::deallocate(copy, p, 1);
}
}
};
auto copy = alloc;
auto const p = traits::allocate(copy, 1);
{
bool constructed = false;
DeferCondDeallocate handler{constructed, copy, p};
traits::construct(copy, p, static_cast<Args&&>(args)...);
constructed = true;
}
return {p, allocator_delete<Alloc>(std::move(copy))};
}
struct SysBufferDeleter {
void operator()(void* ptr) {
std::free(ptr);
}
};
using SysBufferUniquePtr = std::unique_ptr<void, SysBufferDeleter>;
inline SysBufferUniquePtr allocate_sys_buffer(std::size_t size) {
auto p = std::malloc(size);
if (!p) {
throw_exception<std::bad_alloc>();
}
return {p, {}};
}
// # 701 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename Alloc>
struct AllocatorHasTrivialDeallocate : std::false_type {};
template <typename T, class Alloc>
struct AllocatorHasTrivialDeallocate<CxxAllocatorAdaptor<T, Alloc>>
: AllocatorHasTrivialDeallocate<Alloc> {};
namespace detail {
struct AllocatorConstruct_ {
template <typename O, typename... Args>
[[maybe_unused]] inline __attribute__((__always_inline__)) constexpr auto
operator()(O&& o, Args&&... args) const noexcept(noexcept(
static_cast<O&&>(o).construct(static_cast<Args&&>(args)...)))
-> decltype(static_cast<O&&>(o).construct(
static_cast<Args&&>(args)...)) {
return static_cast<O&&>(o).construct(static_cast<Args&&>(args)...);
}
};
struct AllocatorDestroy_ {
template <typename O, typename... Args>
[[maybe_unused]] inline __attribute__((__always_inline__)) constexpr auto
operator()(O&& o, Args&&... args) const noexcept(
noexcept(static_cast<O&&>(o).destroy(static_cast<Args&&>(args)...)))
-> decltype(
static_cast<O&&>(o).destroy(static_cast<Args&&>(args)...)) {
return static_cast<O&&>(o).destroy(static_cast<Args&&>(args)...);
}
};
template <typename Void, typename Alloc, typename... Args>
struct AllocatorCustomizesConstruct_
: folly::is_invocable<AllocatorConstruct_, Alloc, Args...> {};
template <typename Alloc, typename... Args>
struct AllocatorCustomizesConstruct_<
void_t<typename Alloc::folly_has_default_object_construct>,
Alloc,
Args...>
: Negation<typename Alloc::folly_has_default_object_construct> {};
template <typename Void, typename Alloc, typename... Args>
struct AllocatorCustomizesDestroy_
: folly::is_invocable<AllocatorDestroy_, Alloc, Args...> {};
template <typename Alloc, typename... Args>
struct AllocatorCustomizesDestroy_<
void_t<typename Alloc::folly_has_default_object_destroy>,
Alloc,
Args...> : Negation<typename Alloc::folly_has_default_object_destroy> {
};
} // namespace detail
// # 751 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename Alloc, typename T, typename... Args>
struct AllocatorHasDefaultObjectConstruct
: Negation<
detail::AllocatorCustomizesConstruct_<void, Alloc, T*, Args...>> {
};
template <typename Value, typename T, typename... Args>
struct AllocatorHasDefaultObjectConstruct<std::allocator<Value>, T, Args...>
: std::true_type {};
// # 775 "tlm/deps/folly.exploded/include/folly/Memory.h" 3 4
template <typename Alloc, typename T>
struct AllocatorHasDefaultObjectDestroy
: Negation<detail::AllocatorCustomizesDestroy_<void, Alloc, T*>> {};
template <typename Value, typename T>
struct AllocatorHasDefaultObjectDestroy<std::allocator<Value>, T>
: std::true_type {};
} // namespace folly
// # 34 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 2 3
// 4
// # 1 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 2 3 4
// # 31 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
// # 27 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
namespace folly {
template <typename Tuple>
using index_sequence_for_tuple =
std::make_index_sequence<std::tuple_size<Tuple>::value>;
namespace detail {
namespace apply_tuple {
namespace adl {
using std::get;
struct ApplyInvoke {
template <typename T>
using seq = index_sequence_for_tuple<std::remove_reference_t<T>>;
template <typename F, typename T, std::size_t... I>
static constexpr auto
invoke_(F&& f, T&& t, std::index_sequence<I...>) noexcept(
is_nothrow_invocable<F&&,
decltype(get<I>(std::declval<T>()))...>::value)
-> invoke_result_t<F&&, decltype(get<I>(std::declval<T>()))...> {
return invoke(static_cast<F&&>(f), get<I>(static_cast<T&&>(t))...);
}
};
template <typename Tuple,
std::size_t... Indices,
typename ReturnTuple =
std::tuple<decltype(get<Indices>(std::declval<Tuple>()))...>>
auto forward_tuple(Tuple&& tuple, std::index_sequence<Indices...>)
-> ReturnTuple {
return ReturnTuple{get<Indices>(std::forward<Tuple>(tuple))...};
}
} // namespace adl
} // namespace apply_tuple
} // namespace detail
struct ApplyInvoke : private detail::apply_tuple::adl::ApplyInvoke {
public:
template <typename F, typename T>
constexpr auto operator()(F&& f, T&& t) const noexcept(noexcept(
invoke_(static_cast<F&&>(f), static_cast<T&&>(t), seq<T>{})))
-> decltype(invoke_(static_cast<F&&>(f),
static_cast<T&&>(t),
seq<T>{})) {
return invoke_(static_cast<F&&>(f), static_cast<T&&>(t), seq<T>{});
}
};
// # 89 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
using std::apply;
// # 117 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
template <typename Tuple>
auto forward_tuple(Tuple&& tuple) noexcept
-> decltype(detail::apply_tuple::adl::forward_tuple(
std::declval<Tuple>(),
std::declval<index_sequence_for_tuple<
std::remove_reference_t<Tuple>>>())) {
return detail::apply_tuple::adl::forward_tuple(
std::forward<Tuple>(tuple),
index_sequence_for_tuple<std::remove_reference_t<Tuple>>{});
}
template <typename F, typename Tuple>
struct apply_result : invoke_result<ApplyInvoke, F, Tuple> {};
template <typename F, typename Tuple>
using apply_result_t = invoke_result_t<ApplyInvoke, F, Tuple>;
template <typename F, typename Tuple>
struct is_applicable : is_invocable<ApplyInvoke, F, Tuple> {};
template <typename F, typename Tuple>
inline constexpr bool is_applicable_v = is_applicable<F, Tuple>::value;
template <typename R, typename F, typename Tuple>
struct is_applicable_r : is_invocable_r<R, ApplyInvoke, F, Tuple> {};
template <typename R, typename F, typename Tuple>
inline constexpr bool is_applicable_r_v = is_applicable_r<R, F, Tuple>::value;
template <typename F, typename Tuple>
struct is_nothrow_applicable : is_nothrow_invocable<ApplyInvoke, F, Tuple> {};
template <typename F, typename Tuple>
inline constexpr bool is_nothrow_applicable_v =
is_nothrow_applicable<F, Tuple>::value;
template <typename R, typename F, typename Tuple>
struct is_nothrow_applicable_r
: is_nothrow_invocable_r<R, ApplyInvoke, F, Tuple> {};
template <typename R, typename F, typename Tuple>
inline constexpr bool is_nothrow_applicable_r_v =
is_nothrow_applicable_r<R, F, Tuple>::value;
namespace detail {
namespace apply_tuple {
template <class F>
class Uncurry {
public:
explicit Uncurry(F&& func) : func_(std::move(func)) {
}
explicit Uncurry(const F& func) : func_(func) {
}
template <class Tuple>
auto operator()(Tuple&& tuple) const
-> decltype(apply(std::declval<F>(), std::forward<Tuple>(tuple))) {
return apply(func_, std::forward<Tuple>(tuple));
}
private:
F func_;
};
} // namespace apply_tuple
} // namespace detail
// # 197 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
template <class F>
auto uncurry(F&& f)
-> detail::apply_tuple::Uncurry<typename std::decay<F>::type> {
return detail::apply_tuple::Uncurry<typename std::decay<F>::type>(
std::forward<F>(f));
}
using std::make_from_tuple;
// # 231 "tlm/deps/folly.exploded/include/folly/functional/ApplyTuple.h" 3 4
} // namespace folly
// # 32 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 1 3 4
// # 45 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
namespace folly {
namespace hash {
class SpookyHashV1 {
public:
static void Hash128(const void* message,
size_t length,
uint64_t* hash1,
uint64_t* hash2);
static uint64_t Hash64(const void* message, size_t length, uint64_t seed) {
uint64_t hash1 = seed;
Hash128(message, length, &hash1, &seed);
return hash1;
}
static uint32_t Hash32(const void* message, size_t length, uint32_t seed) {
uint64_t hash1 = seed, hash2 = seed;
Hash128(message, length, &hash1, &hash2);
return (uint32_t)hash1;
}
void Init(uint64_t seed1, uint64_t seed2);
void Update(const void* message, size_t length);
// # 116 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
void Final(uint64_t* hash1, uint64_t* hash2);
static inline uint64_t Rot64(uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
// # 141 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
static inline void Mix(const uint64_t* data,
uint64_t& s0,
uint64_t& s1,
uint64_t& s2,
uint64_t& s3,
uint64_t& s4,
uint64_t& s5,
uint64_t& s6,
uint64_t& s7,
uint64_t& s8,
uint64_t& s9,
uint64_t& s10,
uint64_t& s11) {
s0 += data[0];
s2 ^= s10;
s11 ^= s0;
s0 = Rot64(s0, 11);
s11 += s1;
s1 += data[1];
s3 ^= s11;
s0 ^= s1;
s1 = Rot64(s1, 32);
s0 += s2;
s2 += data[2];
s4 ^= s0;
s1 ^= s2;
s2 = Rot64(s2, 43);
s1 += s3;
s3 += data[3];
s5 ^= s1;
s2 ^= s3;
s3 = Rot64(s3, 31);
s2 += s4;
s4 += data[4];
s6 ^= s2;
s3 ^= s4;
s4 = Rot64(s4, 17);
s3 += s5;
s5 += data[5];
s7 ^= s3;
s4 ^= s5;
s5 = Rot64(s5, 28);
s4 += s6;
s6 += data[6];
s8 ^= s4;
s5 ^= s6;
s6 = Rot64(s6, 39);
s5 += s7;
s7 += data[7];
s9 ^= s5;
s6 ^= s7;
s7 = Rot64(s7, 57);
s6 += s8;
s8 += data[8];
s10 ^= s6;
s7 ^= s8;
s8 = Rot64(s8, 55);
s7 += s9;
s9 += data[9];
s11 ^= s7;
s8 ^= s9;
s9 = Rot64(s9, 54);
s8 += s10;
s10 += data[10];
s0 ^= s8;
s9 ^= s10;
s10 = Rot64(s10, 22);
s9 += s11;
s11 += data[11];
s1 ^= s9;
s10 ^= s11;
s11 = Rot64(s11, 46);
s10 += s0;
}
// # 177 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
static inline void EndPartial(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3,
uint64_t& h4,
uint64_t& h5,
uint64_t& h6,
uint64_t& h7,
uint64_t& h8,
uint64_t& h9,
uint64_t& h10,
uint64_t& h11) {
h11 += h1;
h2 ^= h11;
h1 = Rot64(h1, 44);
h0 += h2;
h3 ^= h0;
h2 = Rot64(h2, 15);
h1 += h3;
h4 ^= h1;
h3 = Rot64(h3, 34);
h2 += h4;
h5 ^= h2;
h4 = Rot64(h4, 21);
h3 += h5;
h6 ^= h3;
h5 = Rot64(h5, 38);
h4 += h6;
h7 ^= h4;
h6 = Rot64(h6, 33);
h5 += h7;
h8 ^= h5;
h7 = Rot64(h7, 10);
h6 += h8;
h9 ^= h6;
h8 = Rot64(h8, 13);
h7 += h9;
h10 ^= h7;
h9 = Rot64(h9, 38);
h8 += h10;
h11 ^= h8;
h10 = Rot64(h10, 53);
h9 += h11;
h0 ^= h9;
h11 = Rot64(h11, 42);
h10 += h0;
h1 ^= h10;
h0 = Rot64(h0, 54);
}
static inline void End(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3,
uint64_t& h4,
uint64_t& h5,
uint64_t& h6,
uint64_t& h7,
uint64_t& h8,
uint64_t& h9,
uint64_t& h10,
uint64_t& h11) {
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
}
// # 221 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
static inline void ShortMix(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3) {
h2 = Rot64(h2, 50);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 52);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 30);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 41);
h1 += h2;
h3 ^= h1;
h2 = Rot64(h2, 54);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 48);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 38);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 37);
h1 += h2;
h3 ^= h1;
h2 = Rot64(h2, 62);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 34);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 5);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 36);
h1 += h2;
h3 ^= h1;
}
// # 250 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
static inline void ShortEnd(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3) {
h3 ^= h2;
h2 = Rot64(h2, 15);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 52);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 26);
h1 += h0;
h2 ^= h1;
h1 = Rot64(h1, 51);
h2 += h1;
h3 ^= h2;
h2 = Rot64(h2, 28);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 9);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 47);
h1 += h0;
h2 ^= h1;
h1 = Rot64(h1, 54);
h2 += h1;
h3 ^= h2;
h2 = Rot64(h2, 32);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 25);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 63);
h1 += h0;
}
private:
static void Short(const void* message,
size_t length,
uint64_t* hash1,
uint64_t* hash2);
static const size_t sc_numVars = 12;
static const size_t sc_blockSize = sc_numVars * 8;
static const size_t sc_bufSize = 2 * sc_blockSize;
// # 296 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV1.h" 3 4
static const uint64_t sc_const = 0xdeadbeefdeadbeefULL;
uint64_t m_data[2 * sc_numVars];
uint64_t m_state[sc_numVars];
size_t m_length;
uint8_t m_remainder;
};
} // namespace hash
} // namespace folly
// # 33 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 1 3 4
// # 46 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
namespace folly {
namespace hash {
class SpookyHashV2 {
public:
static void Hash128(const void* message,
size_t length,
uint64_t* hash1,
uint64_t* hash2);
static uint64_t Hash64(const void* message, size_t length, uint64_t seed) {
uint64_t hash1 = seed;
Hash128(message, length, &hash1, &seed);
return hash1;
}
static uint32_t Hash32(const void* message, size_t length, uint32_t seed) {
uint64_t hash1 = seed, hash2 = seed;
Hash128(message, length, &hash1, &hash2);
return (uint32_t)hash1;
}
void Init(uint64_t seed1, uint64_t seed2);
void Update(const void* message, size_t length);
// # 117 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
void Final(uint64_t* hash1, uint64_t* hash2) const;
static inline uint64_t Rot64(uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
// # 142 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
static inline void Mix(const uint64_t* data,
uint64_t& s0,
uint64_t& s1,
uint64_t& s2,
uint64_t& s3,
uint64_t& s4,
uint64_t& s5,
uint64_t& s6,
uint64_t& s7,
uint64_t& s8,
uint64_t& s9,
uint64_t& s10,
uint64_t& s11) {
s0 += data[0];
s2 ^= s10;
s11 ^= s0;
s0 = Rot64(s0, 11);
s11 += s1;
s1 += data[1];
s3 ^= s11;
s0 ^= s1;
s1 = Rot64(s1, 32);
s0 += s2;
s2 += data[2];
s4 ^= s0;
s1 ^= s2;
s2 = Rot64(s2, 43);
s1 += s3;
s3 += data[3];
s5 ^= s1;
s2 ^= s3;
s3 = Rot64(s3, 31);
s2 += s4;
s4 += data[4];
s6 ^= s2;
s3 ^= s4;
s4 = Rot64(s4, 17);
s3 += s5;
s5 += data[5];
s7 ^= s3;
s4 ^= s5;
s5 = Rot64(s5, 28);
s4 += s6;
s6 += data[6];
s8 ^= s4;
s5 ^= s6;
s6 = Rot64(s6, 39);
s5 += s7;
s7 += data[7];
s9 ^= s5;
s6 ^= s7;
s7 = Rot64(s7, 57);
s6 += s8;
s8 += data[8];
s10 ^= s6;
s7 ^= s8;
s8 = Rot64(s8, 55);
s7 += s9;
s9 += data[9];
s11 ^= s7;
s8 ^= s9;
s9 = Rot64(s9, 54);
s8 += s10;
s10 += data[10];
s0 ^= s8;
s9 ^= s10;
s10 = Rot64(s10, 22);
s9 += s11;
s11 += data[11];
s1 ^= s9;
s10 ^= s11;
s11 = Rot64(s11, 46);
s10 += s0;
}
// # 178 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
static inline void EndPartial(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3,
uint64_t& h4,
uint64_t& h5,
uint64_t& h6,
uint64_t& h7,
uint64_t& h8,
uint64_t& h9,
uint64_t& h10,
uint64_t& h11) {
h11 += h1;
h2 ^= h11;
h1 = Rot64(h1, 44);
h0 += h2;
h3 ^= h0;
h2 = Rot64(h2, 15);
h1 += h3;
h4 ^= h1;
h3 = Rot64(h3, 34);
h2 += h4;
h5 ^= h2;
h4 = Rot64(h4, 21);
h3 += h5;
h6 ^= h3;
h5 = Rot64(h5, 38);
h4 += h6;
h7 ^= h4;
h6 = Rot64(h6, 33);
h5 += h7;
h8 ^= h5;
h7 = Rot64(h7, 10);
h6 += h8;
h9 ^= h6;
h8 = Rot64(h8, 13);
h7 += h9;
h10 ^= h7;
h9 = Rot64(h9, 38);
h8 += h10;
h11 ^= h8;
h10 = Rot64(h10, 53);
h9 += h11;
h0 ^= h9;
h11 = Rot64(h11, 42);
h10 += h0;
h1 ^= h10;
h0 = Rot64(h0, 54);
}
static inline void End(const uint64_t* data,
uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3,
uint64_t& h4,
uint64_t& h5,
uint64_t& h6,
uint64_t& h7,
uint64_t& h8,
uint64_t& h9,
uint64_t& h10,
uint64_t& h11) {
h0 += data[0];
h1 += data[1];
h2 += data[2];
h3 += data[3];
h4 += data[4];
h5 += data[5];
h6 += data[6];
h7 += data[7];
h8 += data[8];
h9 += data[9];
h10 += data[10];
h11 += data[11];
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11);
}
// # 226 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
static inline void ShortMix(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3) {
h2 = Rot64(h2, 50);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 52);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 30);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 41);
h1 += h2;
h3 ^= h1;
h2 = Rot64(h2, 54);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 48);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 38);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 37);
h1 += h2;
h3 ^= h1;
h2 = Rot64(h2, 62);
h2 += h3;
h0 ^= h2;
h3 = Rot64(h3, 34);
h3 += h0;
h1 ^= h3;
h0 = Rot64(h0, 5);
h0 += h1;
h2 ^= h0;
h1 = Rot64(h1, 36);
h1 += h2;
h3 ^= h1;
}
// # 255 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
static inline void ShortEnd(uint64_t& h0,
uint64_t& h1,
uint64_t& h2,
uint64_t& h3) {
h3 ^= h2;
h2 = Rot64(h2, 15);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 52);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 26);
h1 += h0;
h2 ^= h1;
h1 = Rot64(h1, 51);
h2 += h1;
h3 ^= h2;
h2 = Rot64(h2, 28);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 9);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 47);
h1 += h0;
h2 ^= h1;
h1 = Rot64(h1, 54);
h2 += h1;
h3 ^= h2;
h2 = Rot64(h2, 32);
h3 += h2;
h0 ^= h3;
h3 = Rot64(h3, 25);
h0 += h3;
h1 ^= h0;
h0 = Rot64(h0, 63);
h1 += h0;
}
private:
static void Short(const void* message,
size_t length,
uint64_t* hash1,
uint64_t* hash2);
static constexpr size_t sc_numVars = 12;
static constexpr size_t sc_blockSize = sc_numVars * 8;
static constexpr size_t sc_bufSize = 2 * sc_blockSize;
// # 301 "tlm/deps/folly.exploded/include/folly/hash/SpookyHashV2.h" 3 4
static constexpr uint64_t sc_const = 0xdeadbeefdeadbeefULL;
uint64_t m_data[2 * sc_numVars];
uint64_t m_state[sc_numVars];
size_t m_length;
uint8_t m_remainder;
};
} // namespace hash
} // namespace folly
// # 34 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 2 3 4
namespace folly {
namespace hash {
inline uint64_t hash_128_to_64(const uint64_t upper,
const uint64_t lower) noexcept {
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (lower ^ upper) * kMul;
a ^= (a >> 47);
uint64_t b = (upper ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
}
inline uint64_t twang_mix64(uint64_t key) noexcept {
key = (~key) + (key << 21);
key = key ^ (key >> 24);
key = key + (key << 3) + (key << 8);
key = key ^ (key >> 14);
key = key + (key << 2) + (key << 4);
key = key ^ (key >> 28);
key = key + (key << 31);
return key;
}
inline uint64_t twang_unmix64(uint64_t key) noexcept {
key *= 4611686016279904257U;
key ^= (key >> 28) ^ (key >> 56);
key *= 14933078535860113213U;
key ^= (key >> 14) ^ (key >> 28) ^ (key >> 42) ^ (key >> 56);
key *= 15244667743933553977U;
key ^= (key >> 24) ^ (key >> 48);
key = (key + 1) * 9223367638806167551U;
return key;
}
inline uint32_t twang_32from64(uint64_t key) noexcept {
key = (~key) + (key << 18);
key = key ^ (key >> 31);
key = key * 21;
key = key ^ (key >> 11);
key = key + (key << 6);
key = key ^ (key >> 22);
return (uint32_t)key;
}
inline uint32_t jenkins_rev_mix32(uint32_t key) noexcept {
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key += (key << 12);
return key;
}
// # 135 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
inline uint32_t jenkins_rev_unmix32(uint32_t key) noexcept {
key *= 2364026753U;
key ^= (key >> 2) ^ (key >> 4) ^ (key >> 6) ^ (key >> 8) ^ (key >> 10) ^
(key >> 12) ^ (key >> 14) ^ (key >> 16) ^ (key >> 18) ^ (key >> 20) ^
(key >> 22) ^ (key >> 24) ^ (key >> 26) ^ (key >> 28) ^ (key >> 30);
key *= 3222273025U;
key ^= (key >> 9) ^ (key >> 18) ^ (key >> 27);
key *= 4042322161U;
key ^= (key >> 22);
key *= 16773121U;
return key;
}
const uint32_t FNV_32_HASH_START = 2166136261UL;
const uint64_t FNV_64_HASH_START = 14695981039346656037ULL;
const uint64_t FNVA_64_HASH_START = 14695981039346656037ULL;
inline uint32_t fnv32(const char* buf,
uint32_t hash = FNV_32_HASH_START) noexcept {
const signed char* s = reinterpret_cast<const signed char*>(buf);
for (; *s; ++s) {
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) +
(hash << 24);
hash ^= *s;
}
return hash;
}
inline uint32_t fnv32_buf(const void* buf,
size_t n,
uint32_t hash = FNV_32_HASH_START) noexcept {
const signed char* char_buf = reinterpret_cast<const signed char*>(buf);
for (size_t i = 0; i < n; ++i) {
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) +
(hash << 24);
hash ^= char_buf[i];
}
return hash;
}
inline uint32_t fnv32(const std::string& str,
uint32_t hash = FNV_32_HASH_START) noexcept {
return fnv32_buf(str.data(), str.size(), hash);
}
inline uint64_t fnv64(const char* buf,
uint64_t hash = FNV_64_HASH_START) noexcept {
const signed char* s = reinterpret_cast<const signed char*>(buf);
for (; *s; ++s) {
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) +
(hash << 8) + (hash << 40);
hash ^= *s;
}
return hash;
}
inline uint64_t fnv64_buf(const void* buf,
size_t n,
uint64_t hash = FNV_64_HASH_START) noexcept {
const signed char* char_buf = reinterpret_cast<const signed char*>(buf);
for (size_t i = 0; i < n; ++i) {
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) +
(hash << 8) + (hash << 40);
hash ^= char_buf[i];
}
return hash;
}
inline uint64_t fnv64(const std::string& str,
uint64_t hash = FNV_64_HASH_START) noexcept {
return fnv64_buf(str.data(), str.size(), hash);
}
inline uint64_t fnva64_buf(const void* buf,
size_t n,
uint64_t hash = FNVA_64_HASH_START) noexcept {
const uint8_t* char_buf = reinterpret_cast<const uint8_t*>(buf);
for (size_t i = 0; i < n; ++i) {
hash ^= char_buf[i];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) +
(hash << 8) + (hash << 40);
}
return hash;
}
inline uint64_t fnva64(const std::string& str,
uint64_t hash = FNVA_64_HASH_START) noexcept {
return fnva64_buf(str.data(), str.size(), hash);
}
inline uint32_t hsieh_hash32_buf(const void* buf, size_t len) noexcept {
const unsigned char* s = reinterpret_cast<const unsigned char*>(buf);
uint32_t hash = static_cast<uint32_t>(len);
uint32_t tmp;
size_t rem;
if (len <= 0 || buf == nullptr) {
return 0;
}
rem = len & 3;
len >>= 2;
for (; len > 0; len--) {
hash += folly::loadUnaligned<uint16_t>(s);
tmp = (folly::loadUnaligned<uint16_t>(s + 2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
s += 2 * sizeof(uint16_t);
hash += hash >> 11;
}
switch (rem) {
case 3:
hash += folly::loadUnaligned<uint16_t>(s);
hash ^= hash << 16;
hash ^= s[sizeof(uint16_t)] << 18;
hash += hash >> 11;
break;
case 2:
hash += folly::loadUnaligned<uint16_t>(s);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1:
hash += *s;
hash ^= hash << 10;
hash += hash >> 1;
}
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
inline uint32_t hsieh_hash32(const char* s) noexcept {
return hsieh_hash32_buf(s, std::strlen(s));
}
inline uint32_t hsieh_hash32_str(const std::string& str) noexcept {
return hsieh_hash32_buf(str.data(), str.size());
}
} // namespace hash
namespace detail {
template <typename I>
struct integral_hasher {
using folly_is_avalanching =
bool_constant<(sizeof(I) >= 8 || sizeof(size_t) == 4)>;
size_t operator()(I const& i) const noexcept {
static_assert(sizeof(I) <= 16, "Input type is too wide");
if (sizeof(I) <= 4) {
auto const i32 = static_cast<int32_t>(i);
auto const u32 = static_cast<uint32_t>(i32);
return static_cast<size_t>(hash::jenkins_rev_mix32(u32));
} else if (sizeof(I) <= 8) {
auto const u64 = static_cast<uint64_t>(i);
return static_cast<size_t>(hash::twang_mix64(u64));
} else {
auto const u = to_unsigned(i);
auto const hi = static_cast<uint64_t>(u >> sizeof(I) * 4);
auto const lo = static_cast<uint64_t>(u);
return hash::hash_128_to_64(hi, lo);
}
}
};
template <typename F>
struct float_hasher {
using folly_is_avalanching = std::true_type;
size_t operator()(F const& f) const noexcept {
static_assert(sizeof(F) <= 8, "Input type is too wide");
if (f == F{}) {
return 0;
}
uint64_t u64 = 0;
memcpy(&u64, &f, sizeof(F));
return static_cast<size_t>(hash::twang_mix64(u64));
}
};
} // namespace detail
template <class Key, class Enable = void>
struct hasher;
struct Hash {
template <class T>
size_t operator()(const T& v) const noexcept(noexcept(hasher<T>()(v))) {
return hasher<T>()(v);
}
template <class T, class... Ts>
size_t operator()(const T& t, const Ts&... ts) const {
return hash::hash_128_to_64((*this)(t), (*this)(ts...));
}
size_t operator()() const noexcept {
return 0;
}
};
// # 429 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
template <typename Hasher, typename Key>
struct IsAvalanchingHasher;
namespace detail {
template <typename Hasher, typename Void = void>
struct IsAvalanchingHasherFromMemberType : std::false_type {};
template <typename Hasher>
struct IsAvalanchingHasherFromMemberType<
Hasher,
void_t<typename Hasher::folly_is_avalanching>>
: bool_constant<Hasher::folly_is_avalanching::value> {};
} // namespace detail
template <typename Hasher, typename Key>
struct IsAvalanchingHasher : detail::IsAvalanchingHasherFromMemberType<Hasher> {
};
template <typename H, typename K>
struct IsAvalanchingHasher<transparent<H>, K> : IsAvalanchingHasher<H, K> {};
template <typename K>
struct IsAvalanchingHasher<Hash, K> : IsAvalanchingHasher<hasher<K>, K> {};
template <>
struct hasher<bool> {
using folly_is_avalanching = std::true_type;
size_t operator()(bool key) const noexcept {
return key ? std::numeric_limits<size_t>::max() : 0;
}
};
template <typename K>
struct IsAvalanchingHasher<hasher<bool>, K> : std::true_type {};
template <>
struct hasher<unsigned long long>
: detail::integral_hasher<unsigned long long> {};
template <>
struct hasher<signed long long> : detail::integral_hasher<signed long long> {};
template <>
struct hasher<unsigned long> : detail::integral_hasher<unsigned long> {};
template <>
struct hasher<signed long> : detail::integral_hasher<signed long> {};
template <>
struct hasher<unsigned int> : detail::integral_hasher<unsigned int> {};
template <>
struct hasher<signed int> : detail::integral_hasher<signed int> {};
template <>
struct hasher<unsigned short> : detail::integral_hasher<unsigned short> {};
template <>
struct hasher<signed short> : detail::integral_hasher<signed short> {};
template <>
struct hasher<unsigned char> : detail::integral_hasher<unsigned char> {};
template <>
struct hasher<signed char> : detail::integral_hasher<signed char> {};
template <>
struct hasher<char> : detail::integral_hasher<char> {};
template <>
struct hasher<signed __int128> : detail::integral_hasher<signed __int128> {};
template <>
struct hasher<unsigned __int128> : detail::integral_hasher<unsigned __int128> {
};
template <>
struct hasher<float> : detail::float_hasher<float> {};
template <>
struct hasher<double> : detail::float_hasher<double> {};
template <>
struct hasher<std::string> {
using folly_is_avalanching = std::true_type;
size_t operator()(const std::string& key) const {
return static_cast<size_t>(
hash::SpookyHashV2::Hash64(key.data(), key.size(), 0));
}
};
template <typename K>
struct IsAvalanchingHasher<hasher<std::string>, K> : std::true_type {};
template <typename T>
struct hasher<T, std::enable_if_t<std::is_enum<T>::value>> {
size_t operator()(T key) const noexcept {
return Hash()(to_underlying(key));
}
};
template <typename T, typename K>
struct IsAvalanchingHasher<hasher<T, std::enable_if_t<std::is_enum<T>::value>>,
K>
: IsAvalanchingHasher<hasher<std::underlying_type_t<T>>, K> {};
template <typename T1, typename T2>
struct hasher<std::pair<T1, T2>> {
using folly_is_avalanching = std::true_type;
size_t operator()(const std::pair<T1, T2>& key) const {
return Hash()(key.first, key.second);
}
};
template <typename... Ts>
struct hasher<std::tuple<Ts...>> {
size_t operator()(const std::tuple<Ts...>& key) const {
return apply(Hash(), key);
}
};
template <typename T>
struct hasher<T*> {
using folly_is_avalanching = hasher<std::uintptr_t>::folly_is_avalanching;
size_t operator()(T* key) const {
return Hash()(bit_cast<std::uintptr_t>(key));
}
};
template <typename T>
struct hasher<std::unique_ptr<T>> {
using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching;
size_t operator()(const std::unique_ptr<T>& key) const {
return Hash()(key.get());
}
};
template <typename T>
struct hasher<std::shared_ptr<T>> {
using folly_is_avalanching = typename hasher<T*>::folly_is_avalanching;
size_t operator()(const std::shared_ptr<T>& key) const {
return Hash()(key.get());
}
};
template <typename T, typename K>
struct IsAvalanchingHasher<hasher<std::tuple<T>>, K>
: IsAvalanchingHasher<hasher<T>, K> {};
template <typename T1, typename T2, typename... Ts, typename K>
struct IsAvalanchingHasher<hasher<std::tuple<T1, T2, Ts...>>, K>
: std::true_type {};
namespace hash {
class StdHasher {
public:
template <typename T>
size_t operator()(const T& t) const noexcept(noexcept(std::hash<T>()(t))) {
return std::hash<T>()(t);
}
};
// # 616 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
template <class Hash, class Value>
uint64_t commutative_hash_combine_value_generic(uint64_t seed,
Hash const& hasher,
Value const& value) {
auto const x = hasher(value);
auto const y = IsAvalanchingHasher<Hash, Value>::value ? x : twang_mix64(x);
return 3860031 + (seed + y) * 2779 + (seed * y * 2);
}
template <
class Iter,
class Hash = std::hash<typename std::iterator_traits<Iter>::value_type>>
uint64_t hash_range(Iter begin,
Iter end,
uint64_t hash = 0,
Hash hasher = Hash()) {
for (; begin != end; ++begin) {
hash = hash_128_to_64(hash, hasher(*begin));
}
return hash;
}
template <class Hash, class Iter>
uint64_t commutative_hash_combine_range_generic(uint64_t seed,
Hash const& hasher,
Iter first,
Iter last) {
while (first != last) {
seed = commutative_hash_combine_value_generic(seed, hasher, *first++);
}
return seed;
}
template <class Iter>
uint64_t commutative_hash_combine_range(Iter first, Iter last) {
return commutative_hash_combine_range_generic(0, Hash{}, first, last);
}
namespace detail {
using c_array_size_t = size_t[];
}
template <class Hasher>
inline size_t hash_combine_generic(const Hasher&) noexcept {
return 0;
}
template <class Hasher, typename T, typename... Ts>
size_t hash_combine_generic(
const Hasher& h,
const T& t,
const Ts&... ts) noexcept(noexcept(detail::c_array_size_t{h(t),
h(ts)...})) {
size_t seed = h(t);
if (sizeof...(ts) == 0) {
return seed;
}
size_t remainder = hash_combine_generic(h, ts...);
if (sizeof(size_t) == sizeof(uint32_t)) {
return twang_32from64((uint64_t(seed) << 32) | remainder);
} else {
return static_cast<size_t>(hash_128_to_64(seed, remainder));
}
}
template <typename Hash, typename... Value>
uint64_t commutative_hash_combine_generic(uint64_t seed,
Hash const& hasher,
Value const&... value) {
uint64_t _[] = {0,
seed = commutative_hash_combine_value_generic(
seed, hasher, value)...};
(void)_;
return seed;
}
template <typename T, typename... Ts>
size_t hash_combine(const T& t, const Ts&... ts) noexcept(
noexcept(hash_combine_generic(StdHasher{}, t, ts...))) {
return hash_combine_generic(StdHasher{}, t, ts...);
}
template <typename... Value>
uint64_t commutative_hash_combine(Value const&... value) {
return commutative_hash_combine_generic(0, Hash{}, value...);
}
} // namespace hash
template <size_t index, typename... Ts>
struct TupleHasher {
size_t operator()(std::tuple<Ts...> const& key) const {
return hash::hash_combine(TupleHasher<index - 1, Ts...>()(key),
std::get<index>(key));
}
};
template <typename... Ts>
struct TupleHasher<0, Ts...> {
size_t operator()(std::tuple<Ts...> const& key) const {
return hash::hash_combine(std::get<0>(key));
}
};
} // namespace folly
namespace std {
// # 747 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
template <typename T1, typename T2>
struct hash<std::pair<T1, T2>> {
using folly_is_avalanching = std::true_type;
size_t operator()(const std::pair<T1, T2>& x) const {
return folly::hash::hash_combine(x.first, x.second);
}
};
template <typename... Ts>
struct hash<std::tuple<Ts...>> {
private:
using FirstT =
std::decay_t<std::tuple_element_t<0, std::tuple<Ts..., bool>>>;
public:
using folly_is_avalanching = folly::bool_constant<(
sizeof...(Ts) != 1 ||
folly::IsAvalanchingHasher<std::hash<FirstT>, FirstT>::value)>;
size_t operator()(std::tuple<Ts...> const& key) const {
folly::TupleHasher<sizeof...(Ts) - 1, Ts...> hasher;
return hasher(key);
}
};
} // namespace std
namespace folly {
// # 787 "tlm/deps/folly.exploded/include/folly/hash/Hash.h" 3 4
template <typename... Args, typename K>
struct IsAvalanchingHasher<std::hash<std::basic_string<Args...>>, K>
: std::true_type {};
} // namespace folly
// # 36 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 2 3
// 4
// # 1 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/PThread.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/PThread.h" 3 4
// # 22 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/SysSyscall.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/SysSyscall.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/portability/SysSyscall.h" 2 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Unistd.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Unistd.h" 3 4
// # 24 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 2 3 4
namespace folly {
// # 42 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 3 4
inline uint64_t getCurrentThreadID() {
return uint64_t(pthread_self());
}
// # 80 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 3 4
inline uint64_t getOSThreadID() {
// # 92 "tlm/deps/folly.exploded/include/folly/system/ThreadId.h" 3 4
return uint64_t(syscall(186));
}
} // namespace folly
// # 39 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 2 3
// 4
namespace folly {
// # 66 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 3 4
struct CacheLocality {
size_t numCpus;
std::vector<size_t> numCachesByLevel;
// # 86 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
std::vector<size_t> localityIndexByCpu;
// # 102 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
template <template <typename> class Atom = std::atomic>
static const CacheLocality& system();
// # 113 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
static CacheLocality readFromSysfsTree(
const std::function<std::string(std::string)>& mapping);
static CacheLocality readFromSysfs();
static CacheLocality readFromProcCpuinfoLines(
std::vector<std::string> const& lines);
static CacheLocality readFromProcCpuinfo();
static CacheLocality uniform(size_t numCpus);
};
struct Getcpu {
typedef int (*Func)(unsigned* cpu, unsigned* node, void* unused);
static Func resolveVdsoFunc();
};
template <template <typename> class Atom>
struct SequentialThreadId {
static unsigned get() {
auto rv = currentId;
if ((__builtin_expect((rv == 0), 0))) {
rv = currentId = ++prevId;
}
return rv;
}
private:
static Atom<unsigned> prevId;
static __thread unsigned currentId;
};
template <template <typename> class Atom>
Atom<unsigned> SequentialThreadId<Atom>::prevId(0);
template <template <typename> class Atom>
__thread unsigned SequentialThreadId<Atom>::currentId(0);
extern template struct SequentialThreadId<std::atomic>;
struct HashingThreadId {
static unsigned get() {
return hash::twang_32from64(getCurrentThreadID());
}
};
template <typename ThreadId>
struct FallbackGetcpu {
static int getcpu(unsigned* cpu, unsigned* node, void*) {
auto id = ThreadId::get();
if (cpu) {
*cpu = id;
}
if (node) {
*node = id;
}
return 0;
}
};
typedef FallbackGetcpu<SequentialThreadId<std::atomic>> FallbackGetcpuType;
// # 245 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 3 4
template <template <typename> class Atom = std::atomic>
struct AccessSpreader {
static size_t current(size_t numStripes) {
(static_cast<bool>(numStripes > 0)
? void(0)
: __assert_fail("numStripes > 0",
"tlm/deps/folly.exploded/include/folly/"
"concurrency/CacheLocality.h",
252,
__extension__ __PRETTY_FUNCTION__));
unsigned cpu;
getcpuFunc(&cpu, nullptr, nullptr);
return widthAndCpuToStripe[std::min(size_t(kMaxCpus), numStripes)]
[cpu % kMaxCpus];
}
// # 267 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
static size_t cachedCurrent(size_t numStripes) {
return widthAndCpuToStripe[std::min(size_t(kMaxCpus), numStripes)]
[cpuCache.cpu()];
}
// # 280 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
static constexpr size_t maxStripeValue() {
return kMaxCpus;
}
private:
enum {
kMaxCpus = kIsMobile ? 16 : 256,
};
typedef uint8_t CompactStripe;
static_assert((kMaxCpus & (kMaxCpus - 1)) == 0,
"kMaxCpus should be a power of two so modulo is fast");
static_assert(kMaxCpus - 1 <= std::numeric_limits<CompactStripe>::max(),
"stripeByCpu element type isn't wide enough");
static Getcpu::Func getcpuFunc;
static CompactStripe widthAndCpuToStripe[kMaxCpus + 1][kMaxCpus];
class CpuCache {
public:
unsigned cpu() {
if ((__builtin_expect((cachedCpuUses_-- == 0), 0))) {
unsigned cpu;
AccessSpreader::getcpuFunc(&cpu, nullptr, nullptr);
cachedCpu_ = cpu % kMaxCpus;
cachedCpuUses_ = kMaxCachedCpuUses - 1;
}
return cachedCpu_;
}
private:
static constexpr unsigned kMaxCachedCpuUses = 32;
unsigned cachedCpu_{0};
unsigned cachedCpuUses_{0};
};
static __thread CpuCache cpuCache;
static bool initialized;
static Getcpu::Func pickGetcpuFunc() {
auto best = Getcpu::resolveVdsoFunc();
return best ? best : &FallbackGetcpuType::getcpu;
}
static int degenerateGetcpu(unsigned* cpu, unsigned* node, void*) {
if (cpu != nullptr) {
*cpu = 0;
}
if (node != nullptr) {
*node = 0;
}
return 0;
}
// # 371 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h"
// 3 4
static bool initialize() {
getcpuFunc = pickGetcpuFunc();
auto& cacheLocality = CacheLocality::system<Atom>();
auto n = cacheLocality.numCpus;
for (size_t width = 0; width <= kMaxCpus; ++width) {
auto& row = widthAndCpuToStripe[width];
auto numStripes = std::max(size_t{1}, width);
for (size_t cpu = 0; cpu < kMaxCpus && cpu < n; ++cpu) {
auto index = cacheLocality.localityIndexByCpu[cpu];
(static_cast<bool>(index < n)
? void(0)
: __assert_fail("index < n",
"tlm/deps/folly.exploded/include/"
"folly/concurrency/CacheLocality.h",
381,
__extension__ __PRETTY_FUNCTION__));
row[cpu] = static_cast<CompactStripe>((index * numStripes) / n);
(static_cast<bool>(row[cpu] < numStripes)
? void(0)
: __assert_fail("row[cpu] < numStripes",
"tlm/deps/folly.exploded/include/"
"folly/concurrency/CacheLocality.h",
385,
__extension__ __PRETTY_FUNCTION__));
}
size_t filled = n;
while (filled < kMaxCpus) {
size_t len = std::min(filled, kMaxCpus - filled);
std::memcpy(&row[filled], &row[0], len);
filled += len;
}
for (size_t cpu = n; cpu < kMaxCpus; ++cpu) {
(static_cast<bool>(row[cpu] == row[cpu - n])
? void(0)
: __assert_fail("row[cpu] == row[cpu - n]",
"tlm/deps/folly.exploded/include/"
"folly/concurrency/CacheLocality.h",
394,
__extension__ __PRETTY_FUNCTION__));
}
}
return true;
}
};
template <template <typename> class Atom>
Getcpu::Func AccessSpreader<Atom>::getcpuFunc =
AccessSpreader<Atom>::degenerateGetcpu;
template <template <typename> class Atom>
typename AccessSpreader<Atom>::CompactStripe
AccessSpreader<Atom>::widthAndCpuToStripe[kMaxCpus + 1][kMaxCpus] = {};
template <template <typename> class Atom>
__thread typename AccessSpreader<Atom>::CpuCache AccessSpreader<Atom>::cpuCache;
template <template <typename> class Atom>
bool AccessSpreader<Atom>::initialized = AccessSpreader<Atom>::initialize();
extern template struct AccessSpreader<std::atomic>;
class SimpleAllocator {
std::mutex m_;
uint8_t* mem_{nullptr};
uint8_t* end_{nullptr};
void* freelist_{nullptr};
size_t allocSize_;
size_t sz_;
std::vector<void*> blocks_;
public:
SimpleAllocator(size_t allocSize, size_t sz);
~SimpleAllocator();
void* allocateHard();
void* allocate() {
std::lock_guard<std::mutex> g(m_);
if (freelist_) {
auto mem = freelist_;
freelist_ = *static_cast<void**>(freelist_);
return mem;
}
if (intptr_t(mem_) % 128 == 0) {
mem_ += std::min(sz_, max_align_v);
}
if (mem_ && (mem_ + sz_ <= end_)) {
auto mem = mem_;
mem_ += sz_;
(static_cast<bool>(intptr_t(mem) % 128 != 0)
? void(0)
: __assert_fail("intptr_t(mem) % 128 != 0",
"tlm/deps/folly.exploded/include/folly/"
"concurrency/CacheLocality.h",
461,
__extension__ __PRETTY_FUNCTION__));
return mem;
}
return allocateHard();
}
void deallocate(void* mem) {
std::lock_guard<std::mutex> g(m_);
*static_cast<void**>(mem) = freelist_;
freelist_ = mem;
}
};
// # 488 "tlm/deps/folly.exploded/include/folly/concurrency/CacheLocality.h" 3 4
template <size_t Stripes>
class CoreRawAllocator {
public:
class Allocator {
static constexpr size_t AllocSize{4096};
uint8_t sizeClass(size_t size) {
if (size <= 8) {
return 0;
} else if (size <= 16) {
return 1;
} else if (size <= 32) {
return 2;
} else if (size <= 64) {
return 3;
} else {
return 4;
}
}
std::array<SimpleAllocator, 4> allocators_{{{AllocSize, 8},
{AllocSize, 16},
{AllocSize, 32},
{AllocSize, 64}}};
public:
void* allocate(size_t size) {
auto cl = sizeClass(size);
if (cl == 4) {
size = size + (hardware_destructive_interference_size - 1);
size &= ~size_t(hardware_destructive_interference_size - 1);
void* mem = aligned_malloc(
size, hardware_destructive_interference_size);
if (!mem) {
throw_exception<std::bad_alloc>();
}
return mem;
}
return allocators_[cl].allocate();
}
void deallocate(void* mem, size_t = 0) {
if (!mem) {
return;
}
if (intptr_t(mem) % 128 != 0) {
auto addr = reinterpret_cast<void*>(intptr_t(mem) &
~intptr_t(AllocSize - 1));
auto allocator = *static_cast<SimpleAllocator**>(addr);
allocator->deallocate(mem);
} else {
aligned_free(mem);
}
}
};
Allocator* get(size_t stripe) {
(static_cast<bool>(stripe < Stripes)
? void(0)
: __assert_fail("stripe < Stripes",
"tlm/deps/folly.exploded/include/folly/"
"concurrency/CacheLocality.h",
545,
__extension__ __PRETTY_FUNCTION__));
return &allocators_[stripe];
}
private:
Allocator allocators_[Stripes];
};
template <typename T, size_t Stripes>
CxxAllocatorAdaptor<T, typename CoreRawAllocator<Stripes>::Allocator>
getCoreAllocator(size_t stripe) {
static Indestructible<CoreRawAllocator<Stripes>> allocator;
return CxxAllocatorAdaptor<T,
typename CoreRawAllocator<Stripes>::Allocator>(
*allocator->get(stripe));
}
} // namespace folly
// # 30 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 2 3 4
namespace folly {
namespace detail {
enum class FutexResult {
VALUE_CHANGED,
AWOKEN,
INTERRUPTED,
TIMEDOUT,
};
// # 50 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 3 4
template <template <typename> class Atom = std::atomic>
using Futex = Atom<std::uint32_t>;
template <typename Futex>
FutexResult futexWait(const Futex* futex,
uint32_t expected,
uint32_t waitMask = -1);
// # 72 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 3 4
template <typename Futex, class Clock, class Duration>
FutexResult futexWaitUntil(
const Futex* futex,
uint32_t expected,
std::chrono::time_point<Clock, Duration> const& deadline,
uint32_t waitMask = -1);
// # 88 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 3 4
template <typename Futex>
int futexWake(const Futex* futex,
int count = std::numeric_limits<int>::max(),
uint32_t wakeMask = -1);
template <typename T>
struct EmulatedFutexAtomic : public std::atomic<T> {
EmulatedFutexAtomic() noexcept = default;
constexpr EmulatedFutexAtomic(T init) noexcept : std::atomic<T>(init) {
}
EmulatedFutexAtomic(EmulatedFutexAtomic&& rhs) = delete;
};
} // namespace detail
} // namespace folly
// # 1 "tlm/deps/folly.exploded/include/folly/detail/Futex-inl.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/Futex-inl.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 1 3
// 4 # 17 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 3
// 4
// # 21 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 2 3
// 4
// # 1 "tlm/deps/folly.exploded/include/folly/Hash.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Hash.h" 3 4
// # 24 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 2 3
// 4
// # 1 "tlm/deps/folly.exploded/include/folly/Unit.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Unit.h" 3 4
namespace folly {
// # 36 "tlm/deps/folly.exploded/include/folly/Unit.h" 3 4
struct Unit {
constexpr bool operator==(const Unit&) const {
return true;
}
constexpr bool operator!=(const Unit&) const {
return false;
}
};
constexpr Unit unit{};
template <typename T>
struct lift_unit {
using type = T;
};
template <>
struct lift_unit<void> {
using type = Unit;
};
template <typename T>
using lift_unit_t = typename lift_unit<T>::type;
template <typename T>
struct drop_unit {
using type = T;
};
template <>
struct drop_unit<Unit> {
using type = void;
};
template <typename T>
using drop_unit_t = typename drop_unit<T>::type;
} // namespace folly
// # 27 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 2 3
// 4 # 1 "tlm/deps/folly.exploded/include/folly/lang/SafeAssert.h" 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/lang/SafeAssert.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/lang/SafeAssert.h" 2 3 4
// # 56 "tlm/deps/folly.exploded/include/folly/lang/SafeAssert.h" 3 4
namespace folly {
namespace detail {
[[noreturn]] void assertionFailure(const char* expr,
const char* msg,
const char* file,
unsigned int line,
const char* function,
int error);
}
} // namespace folly
// # 28 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 2 3
// 4
namespace folly {
namespace parking_lot_detail {
struct WaitNodeBase {
const uint64_t key_;
const uint64_t lotid_;
WaitNodeBase* next_{nullptr};
WaitNodeBase* prev_{nullptr};
bool signaled_;
std::mutex mutex_;
std::condition_variable cond_;
WaitNodeBase(uint64_t key, uint64_t lotid)
: key_(key), lotid_(lotid), signaled_(false) {
}
template <typename Clock, typename Duration>
std::cv_status wait(std::chrono::time_point<Clock, Duration> deadline) {
std::cv_status status = std::cv_status::no_timeout;
std::unique_lock<std::mutex> nodeLock(mutex_);
while (!signaled_ && status != std::cv_status::timeout) {
if (deadline != std::chrono::time_point<Clock, Duration>::max()) {
status = cond_.wait_until(nodeLock, deadline);
} else {
cond_.wait(nodeLock);
}
}
return status;
}
void wake() {
std::lock_guard<std::mutex> nodeLock(mutex_);
signaled_ = true;
cond_.notify_one();
}
bool signaled() {
return signaled_;
}
};
extern std::atomic<uint64_t> idallocator;
struct Bucket {
std::mutex mutex_;
WaitNodeBase* head_;
WaitNodeBase* tail_;
std::atomic<uint64_t> count_;
static Bucket& bucketFor(uint64_t key);
void push_back(WaitNodeBase* node) {
if (tail_) {
((!::folly::kIsDebug || (head_))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(head_)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
89,
__PRETTY_FUNCTION__,
0));
node->prev_ = tail_;
tail_->next_ = node;
tail_ = node;
} else {
tail_ = node;
head_ = node;
}
}
void erase(WaitNodeBase* node) {
((!::folly::kIsDebug || (count_.load(std::memory_order_relaxed) >= 1))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(count_.load(std::memory_order_relaxed) >= 1)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
100,
__PRETTY_FUNCTION__,
0));
if (head_ == node && tail_ == node) {
((!::folly::kIsDebug || (node->prev_ == nullptr))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->prev_ == nullptr)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
102,
__PRETTY_FUNCTION__,
0));
((!::folly::kIsDebug || (node->next_ == nullptr))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->next_ == nullptr)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
103,
__PRETTY_FUNCTION__,
0));
head_ = nullptr;
tail_ = nullptr;
} else if (head_ == node) {
((!::folly::kIsDebug || (node->prev_ == nullptr))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->prev_ == nullptr)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
107,
__PRETTY_FUNCTION__,
0));
((!::folly::kIsDebug || (node->next_))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->next_)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
108,
__PRETTY_FUNCTION__,
0));
head_ = node->next_;
head_->prev_ = nullptr;
} else if (tail_ == node) {
((!::folly::kIsDebug || (node->next_ == nullptr))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->next_ == nullptr)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
112,
__PRETTY_FUNCTION__,
0));
((!::folly::kIsDebug || (node->prev_))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->prev_)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
113,
__PRETTY_FUNCTION__,
0));
tail_ = node->prev_;
tail_->next_ = nullptr;
} else {
((!::folly::kIsDebug || (node->next_))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->next_)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
117,
__PRETTY_FUNCTION__,
0));
((!::folly::kIsDebug || (node->prev_))
? static_cast<void>(0)
: ::folly::detail::assertionFailure(
"(node->prev_)",
(("")),
"tlm/deps/folly.exploded/include/folly/"
"synchronization/ParkingLot.h",
118,
__PRETTY_FUNCTION__,
0));
node->next_->prev_ = node->prev_;
node->prev_->next_ = node->next_;
}
count_.fetch_sub(1, std::memory_order_relaxed);
}
};
} // namespace parking_lot_detail
enum class UnparkControl {
RetainContinue,
RemoveContinue,
RetainBreak,
RemoveBreak,
};
enum class ParkResult {
Skip,
Unpark,
Timeout,
};
// # 161 "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 3
// 4
template <typename Data = Unit>
class ParkingLot {
const uint64_t lotid_;
ParkingLot(const ParkingLot&) = delete;
struct WaitNode : public parking_lot_detail::WaitNodeBase {
const Data data_;
template <typename D>
WaitNode(uint64_t key, uint64_t lotid, D&& data)
: WaitNodeBase(key, lotid), data_(std::forward<D>(data)) {
}
};
public:
ParkingLot() : lotid_(parking_lot_detail::idallocator++) {
}
// # 188
// "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 3 4
template <typename Key, typename D, typename ToPark, typename PreWait>
ParkResult park(const Key key,
D&& data,
ToPark&& toPark,
PreWait&& preWait) {
return park_until(key,
std::forward<D>(data),
std::forward<ToPark>(toPark),
std::forward<PreWait>(preWait),
std::chrono::steady_clock::time_point::max());
}
template <typename Key,
typename D,
typename ToPark,
typename PreWait,
typename Clock,
typename Duration>
ParkResult park_until(const Key key,
D&& data,
ToPark&& toPark,
PreWait&& preWait,
std::chrono::time_point<Clock, Duration> deadline);
template <typename Key,
typename D,
typename ToPark,
typename PreWait,
typename Rep,
typename Period>
ParkResult park_for(const Key key,
D&& data,
ToPark&& toPark,
PreWait&& preWait,
std::chrono::duration<Rep, Period>& timeout) {
return park_until(key,
std::forward<D>(data),
std::forward<ToPark>(toPark),
std::forward<PreWait>(preWait),
timeout + std::chrono::steady_clock::now());
}
// # 244
// "tlm/deps/folly.exploded/include/folly/synchronization/ParkingLot.h" 3 4
template <typename Key, typename Unparker>
void unpark(const Key key, Unparker&& func);
};
template <typename Data>
template <typename Key,
typename D,
typename ToPark,
typename PreWait,
typename Clock,
typename Duration>
ParkResult ParkingLot<Data>::park_until(
const Key bits,
D&& data,
ToPark&& toPark,
PreWait&& preWait,
std::chrono::time_point<Clock, Duration> deadline) {
auto key = hash::twang_mix64(uint64_t(bits));
auto& bucket = parking_lot_detail::Bucket::bucketFor(key);
WaitNode node(key, lotid_, std::forward<D>(data));
{
bucket.count_.fetch_add(1, std::memory_order_seq_cst);
std::unique_lock<std::mutex> bucketLock(bucket.mutex_);
if (!std::forward<ToPark>(toPark)()) {
bucketLock.unlock();
bucket.count_.fetch_sub(1, std::memory_order_relaxed);
return ParkResult::Skip;
}
bucket.push_back(&node);
}
std::forward<PreWait>(preWait)();
auto status = node.wait(deadline);
if (status == std::cv_status::timeout) {
std::lock_guard<std::mutex> bucketLock(bucket.mutex_);
if (!node.signaled()) {
bucket.erase(&node);
return ParkResult::Timeout;
}
}
return ParkResult::Unpark;
}
template <typename Data>
template <typename Key, typename Func>
void ParkingLot<Data>::unpark(const Key bits, Func&& func) {
auto key = hash::twang_mix64(uint64_t(bits));
auto& bucket = parking_lot_detail::Bucket::bucketFor(key);
if (bucket.count_.load(std::memory_order_seq_cst) == 0) {
return;
}
std::lock_guard<std::mutex> bucketLock(bucket.mutex_);
for (auto iter = bucket.head_; iter != nullptr;) {
auto node = static_cast<WaitNode*>(iter);
iter = iter->next_;
if (node->key_ == key && node->lotid_ == lotid_) {
auto result = std::forward<Func>(func)(node->data_);
if (result == UnparkControl::RemoveBreak ||
result == UnparkControl::RemoveContinue) {
bucket.erase(node);
node->wake();
}
if (result == UnparkControl::RemoveBreak ||
result == UnparkControl::RetainBreak) {
return;
}
}
}
}
} // namespace folly
// # 21 "tlm/deps/folly.exploded/include/folly/detail/Futex-inl.h" 2 3 4
namespace folly {
namespace detail {
template <typename TargetClock, typename Clock, typename Duration>
typename TargetClock::time_point time_point_conv(
std::chrono::time_point<Clock, Duration> const& time) {
using std::chrono::duration_cast;
using TimePoint = std::chrono::time_point<Clock, Duration>;
using TargetDuration = typename TargetClock::duration;
using TargetTimePoint = typename TargetClock::time_point;
if (time == TimePoint::max()) {
return TargetTimePoint::max();
} else if (std::is_same<Clock, TargetClock>::value) {
auto const delta = time.time_since_epoch();
return TargetTimePoint(duration_cast<TargetDuration>(delta));
} else {
auto const delta = time - Clock::now();
return TargetClock::now() + duration_cast<TargetDuration>(delta);
}
}
// # 56 "tlm/deps/folly.exploded/include/folly/detail/Futex-inl.h" 3 4
int futexWakeImpl(const Futex<std::atomic>* futex,
int count,
uint32_t wakeMask);
FutexResult futexWaitImpl(
const Futex<std::atomic>* futex,
uint32_t expected,
std::chrono::system_clock::time_point const* absSystemTime,
std::chrono::steady_clock::time_point const* absSteadyTime,
uint32_t waitMask);
int futexWakeImpl(const Futex<EmulatedFutexAtomic>* futex,
int count,
uint32_t wakeMask);
FutexResult futexWaitImpl(
const Futex<EmulatedFutexAtomic>* futex,
uint32_t expected,
std::chrono::system_clock::time_point const* absSystemTime,
std::chrono::steady_clock::time_point const* absSteadyTime,
uint32_t waitMask);
template <typename Futex, typename Deadline>
typename std::enable_if<Deadline::clock::is_steady, FutexResult>::type
futexWaitImpl(Futex* futex,
uint32_t expected,
Deadline const& deadline,
uint32_t waitMask) {
return futexWaitImpl(futex, expected, nullptr, &deadline, waitMask);
}
template <typename Futex, typename Deadline>
typename std::enable_if<!Deadline::clock::is_steady, FutexResult>::type
futexWaitImpl(Futex* futex,
uint32_t expected,
Deadline const& deadline,
uint32_t waitMask) {
return futexWaitImpl(futex, expected, &deadline, nullptr, waitMask);
}
template <typename Futex>
FutexResult futexWait(const Futex* futex,
uint32_t expected,
uint32_t waitMask) {
auto rv = futexWaitImpl(futex, expected, nullptr, nullptr, waitMask);
(static_cast<bool>(rv != FutexResult::TIMEDOUT)
? void(0)
: __assert_fail("rv != FutexResult::TIMEDOUT",
"tlm/deps/folly.exploded/include/folly/detail/"
"Futex-inl.h",
102,
__extension__ __PRETTY_FUNCTION__));
return rv;
}
template <typename Futex>
int futexWake(const Futex* futex, int count, uint32_t wakeMask) {
return futexWakeImpl(futex, count, wakeMask);
}
template <typename Futex, class Clock, class Duration>
FutexResult futexWaitUntil(
const Futex* futex,
uint32_t expected,
std::chrono::time_point<Clock, Duration> const& deadline,
uint32_t waitMask) {
using Target = typename std::conditional<Clock::is_steady,
std::chrono::steady_clock,
std::chrono::system_clock>::type;
auto const converted = time_point_conv<Target>(deadline);
return converted == Target::time_point::max()
? futexWaitImpl(futex, expected, nullptr, nullptr, waitMask)
: futexWaitImpl(futex, expected, converted, waitMask);
}
} // namespace detail
} // namespace folly
// # 110 "tlm/deps/folly.exploded/include/folly/detail/Futex.h" 2 3 4
// # 31 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Asm.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Asm.h" 3 4
// # 27 "tlm/deps/folly.exploded/include/folly/portability/Asm.h" 3 4
namespace folly {
inline void asm_volatile_memory() {
asm volatile("" : : : "memory");
}
inline void asm_volatile_pause() {
asm volatile("pause");
}
} // namespace folly
// # 32 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/SysResource.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/SysResource.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/portability/SysResource.h" 2 3 4
// # 33 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/synchronization/AtomicRef.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/synchronization/AtomicRef.h" 3 4
namespace folly {
namespace detail {
template <typename T>
struct atomic_ref_base {
static_assert(sizeof(T) == sizeof(std::atomic<T>), "size mismatch");
static_assert(alignof(T) == alignof(std::atomic<T>), "alignment mismatch");
static_assert(is_trivially_copyable_v<T>, "value not trivially-copyable");
explicit atomic_ref_base(T& ref) : ref_(ref) {
}
atomic_ref_base(atomic_ref_base const&) = default;
void store(T desired,
std::memory_order order = std::memory_order_seq_cst) const
noexcept {
return atomic().store(desired, order);
}
T load(std::memory_order order = std::memory_order_seq_cst) const noexcept {
return atomic().load(order);
}
bool compare_exchange_weak(T& expected,
T desired,
std::memory_order success,
std::memory_order failure) const noexcept {
return atomic().compare_exchange_weak(
expected, desired, success, failure);
}
bool compare_exchange_weak(
T& expected,
T desired,
std::memory_order order = std::memory_order_seq_cst) const
noexcept {
return atomic().compare_exchange_weak(expected, desired, order);
}
bool compare_exchange_strong(T& expected,
T desired,
std::memory_order success,
std::memory_order failure) const noexcept {
return atomic().compare_exchange_strong(
expected, desired, success, failure);
}
bool compare_exchange_strong(
T& expected,
T desired,
std::memory_order order = std::memory_order_seq_cst) const
noexcept {
return atomic().compare_exchange_strong(expected, desired, order);
}
std::atomic<T>& atomic() const noexcept {
return reinterpret_cast<std::atomic<T>&>(ref_);
}
T& ref_;
};
template <typename T>
struct atomic_ref_integral_base : atomic_ref_base<T> {
using atomic_ref_base<T>::atomic_ref_base;
using atomic_ref_base<T>::atomic;
T fetch_add(T arg,
std::memory_order order = std::memory_order_seq_cst) const
noexcept {
return atomic().fetch_add(arg, order);
}
T fetch_sub(T arg,
std::memory_order order = std::memory_order_seq_cst) const
noexcept {
return atomic().fetch_sub(arg, order);
}
};
template <typename T>
using atomic_ref_select = conditional_t<std::is_integral<T>::value,
atomic_ref_integral_base<T>,
atomic_ref_base<T>>;
} // namespace detail
// # 119 "tlm/deps/folly.exploded/include/folly/synchronization/AtomicRef.h" 3 4
template <typename T>
class atomic_ref : public detail::atomic_ref_select<T> {
private:
using base = detail::atomic_ref_select<T>;
public:
using base::base;
};
template <typename T>
atomic_ref(T&)->atomic_ref<T>;
struct make_atomic_ref_t {
template <typename T,
std::enable_if_t<is_trivially_copyable_v<T> &&
sizeof(T) == sizeof(std::atomic<T>) &&
alignof(T) == alignof(std::atomic<T>),
int> = 0>
atomic_ref<T> operator()(T& ref) const {
return atomic_ref<T>{ref};
}
};
inline constexpr make_atomic_ref_t make_atomic_ref;
} // namespace folly
// # 34 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/synchronization/SanitizeThread.h"
// 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/synchronization/SanitizeThread.h" 3 4
namespace folly {
enum class annotate_rwlock_level : long {
rdlock = 0,
wrlock = 1,
};
namespace detail {
void annotate_rwlock_create_impl(void const volatile* const addr,
char const* const f,
int const l);
void annotate_rwlock_create_static_impl(void const volatile* const addr,
char const* const f,
int const l);
void annotate_rwlock_destroy_impl(void const volatile* const addr,
char const* const f,
int const l);
void annotate_rwlock_acquired_impl(void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l);
void annotate_rwlock_released_impl(void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l);
void annotate_benign_race_sized_impl(const volatile void* addr,
long size,
const char* desc,
const char* f,
int l);
void annotate_ignore_reads_begin_impl(const char* f, int l);
void annotate_ignore_reads_end_impl(const char* f, int l);
void annotate_ignore_writes_begin_impl(const char* f, int l);
void annotate_ignore_writes_end_impl(const char* f, int l);
void annotate_ignore_sync_begin_impl(const char* f, int l);
void annotate_ignore_sync_end_impl(const char* f, int l);
} // namespace detail
inline __attribute__((__always_inline__)) static void annotate_rwlock_create(
void const volatile* const addr, char const* const f, int const l) {
if (kIsSanitizeThread) {
detail::annotate_rwlock_create_impl(addr, f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_rwlock_create_static(void const volatile* const addr,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
detail::annotate_rwlock_create_static_impl(addr, f, l);
}
}
inline __attribute__((__always_inline__)) static void annotate_rwlock_destroy(
void const volatile* const addr, char const* const f, int const l) {
if (kIsSanitizeThread) {
detail::annotate_rwlock_destroy_impl(addr, f, l);
}
}
inline __attribute__((__always_inline__)) static void annotate_rwlock_acquired(
void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
detail::annotate_rwlock_acquired_impl(addr, w, f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_rwlock_try_acquired(void const volatile* const addr,
annotate_rwlock_level const w,
bool const result,
char const* const f,
int const l) {
if (result) {
annotate_rwlock_acquired(addr, w, f, l);
}
}
inline __attribute__((__always_inline__)) static void annotate_rwlock_released(
void const volatile* const addr,
annotate_rwlock_level const w,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
detail::annotate_rwlock_released_impl(addr, w, f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_benign_race_sized(void const volatile* const addr,
long const size,
char const* const desc,
char const* const f,
int const l) {
if (kIsSanitizeThread) {
detail::annotate_benign_race_sized_impl(addr, size, desc, f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_ignore_reads_begin(const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_reads_begin_impl(f, l);
}
}
inline __attribute__((__always_inline__)) static void annotate_ignore_reads_end(
const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_reads_end_impl(f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_ignore_writes_begin(const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_writes_begin_impl(f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_ignore_writes_end(const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_writes_end_impl(f, l);
}
}
inline __attribute__((__always_inline__)) static void
annotate_ignore_sync_begin(const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_sync_begin_impl(f, l);
}
}
inline __attribute__((__always_inline__)) static void annotate_ignore_sync_end(
const char* f, int l) {
if (kIsSanitizeThread) {
detail::annotate_ignore_sync_end_impl(f, l);
}
}
class annotate_ignore_thread_sanitizer_guard {
public:
annotate_ignore_thread_sanitizer_guard(const char* file, int line)
: file_(file), line_(line) {
annotate_ignore_reads_begin(file_, line_);
annotate_ignore_writes_begin(file_, line_);
annotate_ignore_sync_begin(file_, line_);
}
annotate_ignore_thread_sanitizer_guard(
const annotate_ignore_thread_sanitizer_guard&) = delete;
annotate_ignore_thread_sanitizer_guard& operator=(
const annotate_ignore_thread_sanitizer_guard&) = delete;
~annotate_ignore_thread_sanitizer_guard() {
annotate_ignore_reads_end(file_, line_);
annotate_ignore_writes_end(file_, line_);
annotate_ignore_sync_end(file_, line_);
}
private:
const char* file_;
int line_;
};
} // namespace folly
// # 35 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 2 3 4
// # 249 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
namespace folly {
struct SharedMutexToken {
enum class Type : uint16_t {
INVALID = 0,
INLINE_SHARED,
DEFERRED_SHARED,
};
Type type_;
uint16_t slot_;
};
namespace shared_mutex_detail {
std::unique_lock<std::mutex> annotationGuard(void* ptr);
constexpr uint32_t kMaxDeferredReadersAllocated = 256 * 2;
__attribute__((__noinline__)) uint32_t getMaxDeferredReadersSlow(
std::atomic<uint32_t>& cache);
__attribute__((__visibility__("default"))) inline
__attribute__((__always_inline__)) uint32_t
getMaxDeferredReaders() {
static std::atomic<uint32_t> cache{0};
auto const value = cache.load(std::memory_order_acquire);
return (__builtin_expect((!!value), 1)) ? value
: getMaxDeferredReadersSlow(cache);
}
} // namespace shared_mutex_detail
template <bool ReaderPriority,
typename Tag_ = void,
template <typename> class Atom = std::atomic,
bool BlockImmediately = false,
bool AnnotateForThreadSanitizer =
kIsSanitizeThread && !ReaderPriority>
class SharedMutexImpl {
public:
static constexpr bool kReaderPriority = ReaderPriority;
typedef Tag_ Tag;
typedef SharedMutexToken Token;
class [[nodiscard]] ReadHolder;
class [[nodiscard]] UpgradeHolder;
class [[nodiscard]] WriteHolder;
constexpr SharedMutexImpl() noexcept : state_(0) {
}
SharedMutexImpl(const SharedMutexImpl&) = delete;
SharedMutexImpl(SharedMutexImpl&&) = delete;
SharedMutexImpl& operator=(const SharedMutexImpl&) = delete;
SharedMutexImpl& operator=(SharedMutexImpl&&) = delete;
// # 312 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
~SharedMutexImpl() {
auto state = state_.load(std::memory_order_relaxed);
if ((__builtin_expect(((state & kHasS) != 0), 0))) {
cleanupTokenlessSharedDeferred(state);
}
if (folly::kIsDebug) {
(static_cast<bool>((state & ~(kWaitingAny | kMayDefer |
kAnnotationCreated)) == 0)
? void(0)
: __assert_fail("(state & ~(kWaitingAny | kMayDefer | "
"kAnnotationCreated)) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
326,
__extension__ __PRETTY_FUNCTION__));
if ((state & kMayDefer) != 0) {
const uint32_t maxDeferredReaders =
shared_mutex_detail::getMaxDeferredReaders();
for (uint32_t slot = 0; slot < maxDeferredReaders; ++slot) {
auto slotValue = deferredReader(slot)->load(
std::memory_order_relaxed);
(static_cast<bool>(!slotValueIsThis(slotValue))
? void(0)
: __assert_fail(
"!slotValueIsThis(slotValue)",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
333,
__extension__ __PRETTY_FUNCTION__));
(void)slotValue;
}
}
}
annotateDestroy();
}
bool eligible_for_lock_elision() const {
auto state = state_.load(std::memory_order_relaxed);
return (state & (kHasS | kMayDefer | kHasE | kHasU)) == 0;
}
bool eligible_for_lock_upgrade_elision() const {
auto state = state_.load(std::memory_order_relaxed);
return (state & (kHasE | kHasU)) == 0;
}
bool eligible_for_lock_shared_elision() const {
auto state = state_.load(std::memory_order_relaxed);
return (state & kHasE) == 0;
}
void lock() {
WaitForever ctx;
(void)lockExclusiveImpl(kHasSolo, ctx);
annotateAcquired(annotate_rwlock_level::wrlock);
}
bool try_lock() {
WaitNever ctx;
auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result;
}
template <class Rep, class Period>
bool try_lock_for(const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration);
auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result;
}
template <class Clock, class Duration>
bool try_lock_until(
const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockExclusiveImpl(kHasSolo, ctx);
annotateTryAcquired(result, annotate_rwlock_level::wrlock);
return result;
}
void unlock() {
annotateReleased(annotate_rwlock_level::wrlock);
auto state = (state_ &= ~(kWaitingNotS | kPrevDefer | kHasE));
(static_cast<bool>((state & ~(kWaitingAny | kAnnotationCreated)) == 0)
? void(0)
: __assert_fail(
"(state & ~(kWaitingAny | kAnnotationCreated)) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
405,
__extension__ __PRETTY_FUNCTION__));
wakeRegisteredWaiters(state, kWaitingE | kWaitingU | kWaitingS);
}
void lock_shared() {
WaitForever ctx;
(void)lockSharedImpl(nullptr, ctx);
annotateAcquired(annotate_rwlock_level::rdlock);
}
void lock_shared(Token& token) {
WaitForever ctx;
(void)lockSharedImpl(&token, ctx);
annotateAcquired(annotate_rwlock_level::rdlock);
}
bool try_lock_shared() {
WaitNever ctx;
auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
bool try_lock_shared(Token& token) {
WaitNever ctx;
auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Rep, class Period>
bool try_lock_shared_for(
const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration);
auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Rep, class Period>
bool try_lock_shared_for(const std::chrono::duration<Rep, Period>& duration,
Token& token) {
WaitForDuration<Rep, Period> ctx(duration);
auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Clock, class Duration>
bool try_lock_shared_until(
const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockSharedImpl(nullptr, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Clock, class Duration>
bool try_lock_shared_until(
const std::chrono::time_point<Clock, Duration>& absDeadline,
Token& token) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockSharedImpl(&token, ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
void unlock_shared() {
annotateReleased(annotate_rwlock_level::rdlock);
auto state = state_.load(std::memory_order_acquire);
(static_cast<bool>((state & (kPrevDefer | kHasE | kBegunE)) !=
kPrevDefer)
? void(0)
: __assert_fail("(state & (kPrevDefer | kHasE | kBegunE)) != "
"kPrevDefer",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
480,
__extension__ __PRETTY_FUNCTION__));
if ((state & (kMayDefer | kPrevDefer)) == 0 ||
!tryUnlockTokenlessSharedDeferred()) {
unlockSharedInline();
}
}
void unlock_shared(Token& token) {
annotateReleased(annotate_rwlock_level::rdlock);
(static_cast<bool>(token.type_ == Token::Type::INLINE_SHARED ||
token.type_ == Token::Type::DEFERRED_SHARED)
? void(0)
: __assert_fail("token.type_ == Token::Type::INLINE_SHARED || "
"token.type_ == Token::Type::DEFERRED_SHARED",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
496,
__extension__ __PRETTY_FUNCTION__))
;
if (token.type_ != Token::Type::DEFERRED_SHARED ||
!tryUnlockSharedDeferred(token.slot_)) {
unlockSharedInline();
}
if (folly::kIsDebug) {
token.type_ = Token::Type::INVALID;
}
}
void unlock_and_lock_shared() {
annotateReleased(annotate_rwlock_level::wrlock);
annotateAcquired(annotate_rwlock_level::rdlock);
auto state = state_.load(std::memory_order_acquire);
do {
(static_cast<bool>((state & ~(kWaitingAny | kPrevDefer |
kAnnotationCreated)) == kHasE)
? void(0)
: __assert_fail("(state & ~(kWaitingAny | kPrevDefer | "
"kAnnotationCreated)) == kHasE",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
520,
__extension__ __PRETTY_FUNCTION__));
} while (!state_.compare_exchange_strong(
state,
(state & ~(kWaitingAny | kPrevDefer | kHasE)) + kIncrHasS));
if ((state & (kWaitingE | kWaitingU | kWaitingS)) != 0) {
futexWakeAll(kWaitingE | kWaitingU | kWaitingS);
}
}
void unlock_and_lock_shared(Token& token) {
unlock_and_lock_shared();
token.type_ = Token::Type::INLINE_SHARED;
}
void lock_upgrade() {
WaitForever ctx;
(void)lockUpgradeImpl(ctx);
annotateAcquired(annotate_rwlock_level::rdlock);
}
bool try_lock_upgrade() {
WaitNever ctx;
auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Rep, class Period>
bool try_lock_upgrade_for(
const std::chrono::duration<Rep, Period>& duration) {
WaitForDuration<Rep, Period> ctx(duration);
auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
template <class Clock, class Duration>
bool try_lock_upgrade_until(
const std::chrono::time_point<Clock, Duration>& absDeadline) {
WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
auto result = lockUpgradeImpl(ctx);
annotateTryAcquired(result, annotate_rwlock_level::rdlock);
return result;
}
void unlock_upgrade() {
annotateReleased(annotate_rwlock_level::rdlock);
auto state = (state_ -= kHasU);
(static_cast<bool>((state & (kWaitingNotS | kHasSolo)) == 0)
? void(0)
: __assert_fail("(state & (kWaitingNotS | kHasSolo)) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
569,
__extension__ __PRETTY_FUNCTION__));
wakeRegisteredWaiters(state, kWaitingE | kWaitingU);
}
void unlock_upgrade_and_lock() {
WaitForever ctx;
(void)lockExclusiveImpl(0, ctx);
annotateReleased(annotate_rwlock_level::rdlock);
annotateAcquired(annotate_rwlock_level::wrlock);
}
void unlock_upgrade_and_lock_shared() {
auto state = (state_ -= kHasU - kIncrHasS);
(static_cast<bool>((state & (kWaitingNotS | kHasSolo)) == 0)
? void(0)
: __assert_fail("(state & (kWaitingNotS | kHasSolo)) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
585,
__extension__ __PRETTY_FUNCTION__));
wakeRegisteredWaiters(state, kWaitingE | kWaitingU);
}
void unlock_upgrade_and_lock_shared(Token& token) {
unlock_upgrade_and_lock_shared();
token.type_ = Token::Type::INLINE_SHARED;
}
void unlock_and_lock_upgrade() {
annotateReleased(annotate_rwlock_level::wrlock);
annotateAcquired(annotate_rwlock_level::rdlock);
auto state = state_.load(std::memory_order_acquire);
while (true) {
(static_cast<bool>((state & ~(kWaitingAny | kPrevDefer |
kAnnotationCreated)) == kHasE)
? void(0)
: __assert_fail("(state & ~(kWaitingAny | kPrevDefer | "
"kAnnotationCreated)) == kHasE",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
602,
__extension__ __PRETTY_FUNCTION__));
auto after =
(state & ~(kWaitingNotS | kWaitingS | kPrevDefer | kHasE)) +
kHasU;
if (state_.compare_exchange_strong(state, after)) {
if ((state & kWaitingS) != 0) {
futexWakeAll(kWaitingS);
}
return;
}
}
}
private:
typedef typename folly::detail::Futex<Atom> Futex;
struct WaitForever {
bool canBlock() {
return true;
}
bool canTimeOut() {
return false;
}
bool shouldTimeOut() {
return false;
}
bool doWait(Futex& futex, uint32_t expected, uint32_t waitMask) {
detail::futexWait(&futex, expected, waitMask);
return true;
}
};
struct WaitNever {
bool canBlock() {
return false;
}
bool canTimeOut() {
return true;
}
bool shouldTimeOut() {
return true;
}
bool doWait(Futex&, uint32_t, uint32_t) {
return false;
}
};
template <class Rep, class Period>
struct WaitForDuration {
std::chrono::duration<Rep, Period> duration_;
bool deadlineComputed_;
std::chrono::steady_clock::time_point deadline_;
explicit WaitForDuration(
const std::chrono::duration<Rep, Period>& duration)
: duration_(duration), deadlineComputed_(false) {
}
std::chrono::steady_clock::time_point deadline() {
if (!deadlineComputed_) {
deadline_ = std::chrono::steady_clock::now() + duration_;
deadlineComputed_ = true;
}
return deadline_;
}
bool canBlock() {
return duration_.count() > 0;
}
bool canTimeOut() {
return true;
}
bool shouldTimeOut() {
return std::chrono::steady_clock::now() > deadline();
}
bool doWait(Futex& futex, uint32_t expected, uint32_t waitMask) {
auto result = detail::futexWaitUntil(
&futex, expected, deadline(), waitMask);
return result != folly::detail::FutexResult::TIMEDOUT;
}
};
template <class Clock, class Duration>
struct WaitUntilDeadline {
std::chrono::time_point<Clock, Duration> absDeadline_;
bool canBlock() {
return true;
}
bool canTimeOut() {
return true;
}
bool shouldTimeOut() {
return Clock::now() > absDeadline_;
}
bool doWait(Futex& futex, uint32_t expected, uint32_t waitMask) {
auto result = detail::futexWaitUntil(
&futex, expected, absDeadline_, waitMask);
return result != folly::detail::FutexResult::TIMEDOUT;
}
};
void annotateLazyCreate() {
if (AnnotateForThreadSanitizer &&
(state_.load() & kAnnotationCreated) == 0) {
auto guard = shared_mutex_detail::annotationGuard(this);
if ((state_.load() & kAnnotationCreated) == 0) {
state_.fetch_or(kAnnotationCreated);
annotate_benign_race_sized(
&state_,
sizeof(state_),
"init TSAN",
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
724);
annotate_rwlock_create(
this,
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
725);
}
}
}
void annotateDestroy() {
if (AnnotateForThreadSanitizer) {
annotateLazyCreate();
annotate_rwlock_destroy(
this,
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
733);
}
}
void annotateAcquired(annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) {
annotateLazyCreate();
annotate_rwlock_acquired(
this,
w,
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
740);
}
}
void annotateTryAcquired(bool result, annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) {
annotateLazyCreate();
annotate_rwlock_try_acquired(
this,
w,
result,
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
747);
}
}
void annotateReleased(annotate_rwlock_level w) {
if (AnnotateForThreadSanitizer) {
(static_cast<bool>((state_.load() & kAnnotationCreated) != 0)
? void(0)
: __assert_fail(
"(state_.load() & kAnnotationCreated) != 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
753,
__extension__ __PRETTY_FUNCTION__));
annotate_rwlock_released(
this,
w,
"tlm/deps/folly.exploded/include/folly/SharedMutex.h",
754);
}
}
Futex state_{};
// # 769 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
static constexpr uint32_t kIncrHasS = 1 << 11;
static constexpr uint32_t kHasS = ~(kIncrHasS - 1);
static constexpr uint32_t kAnnotationCreated = 1 << 10;
static constexpr uint32_t kMayDefer = 1 << 9;
static constexpr uint32_t kPrevDefer = 1 << 8;
static constexpr uint32_t kHasE = 1 << 7;
static constexpr uint32_t kBegunE = 1 << 6;
// # 809 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
static constexpr uint32_t kHasU = 1 << 5;
static constexpr uint32_t kHasSolo = kHasE | kBegunE | kHasU;
static constexpr uint32_t kWaitingNotS = 1 << 4;
// # 834 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
static constexpr uint32_t kWaitingESingle = 1 << 2;
static constexpr uint32_t kWaitingEMultiple = 1 << 3;
static constexpr uint32_t kWaitingE = kWaitingESingle | kWaitingEMultiple;
static constexpr uint32_t kWaitingU = 1 << 1;
static constexpr uint32_t kWaitingS = 1 << 0;
static constexpr uint32_t kWaitingAny =
kWaitingNotS | kWaitingE | kWaitingU | kWaitingS;
static constexpr uint32_t kNumSharedToStartDeferring = 2;
static constexpr uint32_t kMaxSpinCount = !BlockImmediately ? 1000 : 2;
static constexpr uint32_t kMaxSoftYieldCount = !BlockImmediately ? 1000 : 0;
// # 899 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
public:
static constexpr uint32_t kDeferredSearchDistance = 2;
static constexpr uint32_t kDeferredSeparationFactor = 4;
private:
static_assert(!(kDeferredSearchDistance & (kDeferredSearchDistance - 1)),
"kDeferredSearchDistance must be a power of 2");
static constexpr uint32_t kTokenStackTLSCapacity = 2;
// # 924 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
static constexpr uintptr_t kTokenless = 0x1;
static __thread uint32_t tls_lastTokenlessSlot;
static __thread uint32_t tls_lastDeferredReaderSlot;
public:
typedef Atom<uintptr_t> DeferredReaderSlot;
private:
alignas(hardware_destructive_interference_size) static DeferredReaderSlot
deferredReaders[shared_mutex_detail::kMaxDeferredReadersAllocated *
kDeferredSeparationFactor];
template <class WaitContext>
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext& ctx) {
uint32_t state = state_.load(std::memory_order_acquire);
if ((__builtin_expect(((state & (preconditionGoalMask | kMayDefer |
kHasS)) == 0 &&
state_.compare_exchange_strong(
state, (state | kHasE) & ~kHasU)),
1))
) {
return true;
} else {
return lockExclusiveImpl(state, preconditionGoalMask, ctx);
}
}
template <class WaitContext>
bool lockExclusiveImpl(uint32_t& state,
uint32_t preconditionGoalMask,
WaitContext& ctx) {
while (true) {
if ((__builtin_expect(((state & preconditionGoalMask) != 0), 0)) &&
!waitForZeroBits(state, preconditionGoalMask, kWaitingE, ctx) &&
ctx.canTimeOut()) {
return false;
}
uint32_t after = (state & kMayDefer) == 0 ? 0 : kPrevDefer;
if (!kReaderPriority || (state & (kMayDefer | kHasS)) == 0) {
after |= (state | kHasE) & ~(kHasU | kMayDefer);
} else {
after |= (state | kBegunE) & ~(kHasU | kMayDefer);
}
if (state_.compare_exchange_strong(state, after)) {
auto before = state;
state = after;
// # 996 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3
// 4
if ((__builtin_expect(((before & kMayDefer) != 0), 0))) {
applyDeferredReaders(state, ctx);
}
while (true) {
(static_cast<bool>((state & (kHasE | kBegunE)) != 0 &&
(state & kHasU) == 0)
? void(0)
: __assert_fail(
"(state & (kHasE | kBegunE)) != 0 && "
"(state & kHasU) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1000,
__extension__ __PRETTY_FUNCTION__));
if ((__builtin_expect(((state & kHasS) != 0), 0)) &&
!waitForZeroBits(state, kHasS, kWaitingNotS, ctx) &&
ctx.canTimeOut()) {
state = (state_ &= ~(kPrevDefer | kHasE | kBegunE |
kWaitingNotS));
wakeRegisteredWaiters(
state, kWaitingE | kWaitingU | kWaitingS);
return false;
}
if (kReaderPriority && (state & kHasE) == 0) {
(static_cast<bool>((state & kBegunE) != 0)
? void(0)
: __assert_fail(
"(state & kBegunE) != 0",
"tlm/deps/folly.exploded/include/"
"folly/SharedMutex.h",
1014,
__extension__ __PRETTY_FUNCTION__));
if (!state_.compare_exchange_strong(
state, (state & ~kBegunE) | kHasE)) {
continue;
}
}
return true;
}
}
}
}
template <class WaitContext>
bool waitForZeroBits(uint32_t& state,
uint32_t goal,
uint32_t waitMask,
WaitContext& ctx) {
uint32_t spinCount = 0;
while (true) {
state = state_.load(std::memory_order_acquire);
if ((state & goal) == 0) {
return true;
}
asm_volatile_pause();
++spinCount;
if ((__builtin_expect((spinCount >= kMaxSpinCount), 0))) {
return ctx.canBlock() &&
yieldWaitForZeroBits(state, goal, waitMask, ctx);
}
}
}
template <class WaitContext>
bool yieldWaitForZeroBits(uint32_t& state,
uint32_t goal,
uint32_t waitMask,
WaitContext& ctx) {
struct rusage usage;
std::memset(&usage, 0, sizeof(usage));
long before = -1;
for (uint32_t yieldCount = 0; yieldCount < kMaxSoftYieldCount;
++yieldCount) {
for (int softState = 0; softState < 3; ++softState) {
if (softState < 2) {
std::this_thread::yield();
} else {
getrusage(RUSAGE_THREAD, &usage);
}
if (((state = state_.load(std::memory_order_acquire)) & goal) ==
0) {
return true;
}
if (ctx.shouldTimeOut()) {
return false;
}
}
if (before >= 0 && usage.ru_nivcsw >= before + 2) {
break;
}
before = usage.ru_nivcsw;
}
return futexWaitForZeroBits(state, goal, waitMask, ctx);
}
template <class WaitContext>
bool futexWaitForZeroBits(uint32_t& state,
uint32_t goal,
uint32_t waitMask,
WaitContext& ctx) {
(static_cast<bool>(waitMask == kWaitingNotS || waitMask == kWaitingE ||
waitMask == kWaitingU || waitMask == kWaitingS)
? void(0)
: __assert_fail(
"waitMask == kWaitingNotS || waitMask == kWaitingE "
"|| waitMask == kWaitingU || waitMask == kWaitingS",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1095,
__extension__ __PRETTY_FUNCTION__))
;
while (true) {
state = state_.load(std::memory_order_acquire);
if ((state & goal) == 0) {
return true;
}
auto after = state;
if (waitMask == kWaitingE) {
if ((state & kWaitingESingle) != 0) {
after |= kWaitingEMultiple;
} else {
after |= kWaitingESingle;
}
} else {
after |= waitMask;
}
if (after != state &&
!state_.compare_exchange_strong(state, after)) {
continue;
}
if (!ctx.doWait(state_, after, waitMask)) {
return false;
}
}
}
void wakeRegisteredWaiters(uint32_t& state, uint32_t wakeMask) {
if ((__builtin_expect(((state & wakeMask) != 0), 0))) {
wakeRegisteredWaitersImpl(state, wakeMask);
}
}
void wakeRegisteredWaitersImpl(uint32_t& state, uint32_t wakeMask) {
// # 1153 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
if ((wakeMask & kWaitingE) == kWaitingE &&
(state & wakeMask) == kWaitingE &&
detail::futexWake(&state_, 1, kWaitingE) > 0) {
return;
}
if ((state & wakeMask) != 0) {
auto prev = state_.fetch_and(~wakeMask);
if ((prev & wakeMask) != 0) {
futexWakeAll(wakeMask);
}
state = prev & ~wakeMask;
}
}
void futexWakeAll(uint32_t wakeMask) {
detail::futexWake(&state_, std::numeric_limits<int>::max(), wakeMask);
}
DeferredReaderSlot* deferredReader(uint32_t slot) {
return &deferredReaders[slot * kDeferredSeparationFactor];
}
uintptr_t tokenfulSlotValue() {
return reinterpret_cast<uintptr_t>(this);
}
uintptr_t tokenlessSlotValue() {
return tokenfulSlotValue() | kTokenless;
}
bool slotValueIsThis(uintptr_t slotValue) {
return (slotValue & ~kTokenless) == tokenfulSlotValue();
}
template <class WaitContext>
void applyDeferredReaders(uint32_t& state, WaitContext& ctx) {
uint32_t slot = 0;
uint32_t spinCount = 0;
const uint32_t maxDeferredReaders =
shared_mutex_detail::getMaxDeferredReaders();
while (true) {
while (!slotValueIsThis(
deferredReader(slot)->load(std::memory_order_acquire))) {
if (++slot == maxDeferredReaders) {
return;
}
}
asm_volatile_pause();
if ((__builtin_expect((++spinCount >= kMaxSpinCount), 0))) {
applyDeferredReaders(state, ctx, slot);
return;
}
}
}
template <class WaitContext>
void applyDeferredReaders(uint32_t& state,
WaitContext& ctx,
uint32_t slot) {
struct rusage usage;
std::memset(&usage, 0, sizeof(usage));
long before = -1;
const uint32_t maxDeferredReaders =
shared_mutex_detail::getMaxDeferredReaders();
for (uint32_t yieldCount = 0; yieldCount < kMaxSoftYieldCount;
++yieldCount) {
for (int softState = 0; softState < 3; ++softState) {
if (softState < 2) {
std::this_thread::yield();
} else {
getrusage(RUSAGE_THREAD, &usage);
}
while (!slotValueIsThis(deferredReader(slot)->load(
std::memory_order_acquire))) {
if (++slot == maxDeferredReaders) {
return;
}
}
if (ctx.shouldTimeOut()) {
break;
}
}
if (before >= 0 && usage.ru_nivcsw >= before + 2) {
break;
}
before = usage.ru_nivcsw;
}
uint32_t movedSlotCount = 0;
for (; slot < maxDeferredReaders; ++slot) {
auto slotPtr = deferredReader(slot);
auto slotValue = slotPtr->load(std::memory_order_acquire);
if (slotValueIsThis(slotValue) &&
slotPtr->compare_exchange_strong(slotValue, 0)) {
++movedSlotCount;
}
}
if (movedSlotCount > 0) {
state = (state_ += movedSlotCount * kIncrHasS);
}
(static_cast<bool>((state & (kHasE | kBegunE)) != 0)
? void(0)
: __assert_fail("(state & (kHasE | kBegunE)) != 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1267,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(state < state + kIncrHasS)
? void(0)
: __assert_fail("state < state + kIncrHasS",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1272,
__extension__ __PRETTY_FUNCTION__));
}
// # 1288 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
template <class WaitContext>
bool lockSharedImpl(Token* token, WaitContext& ctx) {
uint32_t state = state_.load(std::memory_order_relaxed);
if ((state & (kHasS | kMayDefer | kHasE)) == 0 &&
state_.compare_exchange_strong(state, state + kIncrHasS)) {
if (token != nullptr) {
token->type_ = Token::Type::INLINE_SHARED;
}
return true;
}
return lockSharedImpl(state, token, ctx);
}
template <class WaitContext>
bool lockSharedImpl(uint32_t& state, Token* token, WaitContext& ctx);
void cleanupTokenlessSharedDeferred(uint32_t& state) {
const uint32_t maxDeferredReaders =
shared_mutex_detail::getMaxDeferredReaders();
for (uint32_t i = 0; i < maxDeferredReaders; ++i) {
auto slotPtr = deferredReader(i);
auto slotValue = slotPtr->load(std::memory_order_relaxed);
if (slotValue == tokenlessSlotValue()) {
slotPtr->store(0, std::memory_order_relaxed);
state += kIncrHasS;
if ((state & kHasS) == 0) {
break;
}
}
}
}
bool tryUnlockTokenlessSharedDeferred();
bool tryUnlockSharedDeferred(uint32_t slot) {
(static_cast<bool>(slot < shared_mutex_detail::getMaxDeferredReaders())
? void(0)
: __assert_fail("slot < "
"shared_mutex_detail::getMaxDeferredReaders()",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1325,
__extension__ __PRETTY_FUNCTION__));
auto slotValue = tokenfulSlotValue();
return deferredReader(slot)->compare_exchange_strong(slotValue, 0);
}
uint32_t unlockSharedInline() {
uint32_t state = (state_ -= kIncrHasS);
(static_cast<bool>((state & (kHasE | kBegunE | kMayDefer)) != 0 ||
state < state + kIncrHasS)
? void(0)
: __assert_fail("(state & (kHasE | kBegunE | kMayDefer)) != 0 "
"|| state < state + kIncrHasS",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1332,
__extension__ __PRETTY_FUNCTION__))
;
if ((state & kHasS) == 0) {
wakeRegisteredWaiters(state, kWaitingNotS);
}
return state;
}
template <class WaitContext>
bool lockUpgradeImpl(WaitContext& ctx) {
uint32_t state;
do {
if (!waitForZeroBits(state, kHasSolo, kWaitingU, ctx)) {
return false;
}
} while (!state_.compare_exchange_strong(state, state | kHasU));
return true;
}
public:
class [[nodiscard]] ReadHolder {
ReadHolder() : lock_(nullptr) {
}
public:
explicit ReadHolder(const SharedMutexImpl* lock)
: lock_(const_cast<SharedMutexImpl*>(lock)) {
if (lock_) {
lock_->lock_shared(token_);
}
}
explicit ReadHolder(const SharedMutexImpl& lock)
: lock_(const_cast<SharedMutexImpl*>(&lock)) {
lock_->lock_shared(token_);
}
ReadHolder(ReadHolder && rhs) noexcept
: lock_(rhs.lock_), token_(rhs.token_) {
rhs.lock_ = nullptr;
}
explicit ReadHolder(UpgradeHolder && upgraded) : lock_(upgraded.lock_) {
(static_cast<bool>(upgraded.lock_ != nullptr)
? void(0)
: __assert_fail("upgraded.lock_ != nullptr",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1378,
__extension__ __PRETTY_FUNCTION__));
upgraded.lock_ = nullptr;
lock_->unlock_upgrade_and_lock_shared(token_);
}
explicit ReadHolder(WriteHolder && writer) : lock_(writer.lock_) {
(static_cast<bool>(writer.lock_ != nullptr)
? void(0)
: __assert_fail("writer.lock_ != nullptr",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1385,
__extension__ __PRETTY_FUNCTION__));
writer.lock_ = nullptr;
lock_->unlock_and_lock_shared(token_);
}
ReadHolder& operator=(ReadHolder&& rhs) noexcept {
std::swap(lock_, rhs.lock_);
std::swap(token_, rhs.token_);
return *this;
}
ReadHolder(const ReadHolder& rhs) = delete;
ReadHolder& operator=(const ReadHolder& rhs) = delete;
~ReadHolder() {
unlock();
}
void unlock() {
if (lock_) {
lock_->unlock_shared(token_);
lock_ = nullptr;
}
}
private:
friend class UpgradeHolder;
friend class WriteHolder;
SharedMutexImpl* lock_;
SharedMutexToken token_;
};
class [[nodiscard]] UpgradeHolder {
UpgradeHolder() : lock_(nullptr) {
}
public:
explicit UpgradeHolder(SharedMutexImpl * lock) : lock_(lock) {
if (lock_) {
lock_->lock_upgrade();
}
}
explicit UpgradeHolder(SharedMutexImpl & lock) : lock_(&lock) {
lock_->lock_upgrade();
}
explicit UpgradeHolder(WriteHolder && writer) : lock_(writer.lock_) {
(static_cast<bool>(writer.lock_ != nullptr)
? void(0)
: __assert_fail("writer.lock_ != nullptr",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1433,
__extension__ __PRETTY_FUNCTION__));
writer.lock_ = nullptr;
lock_->unlock_and_lock_upgrade();
}
UpgradeHolder(UpgradeHolder && rhs) noexcept : lock_(rhs.lock_) {
rhs.lock_ = nullptr;
}
UpgradeHolder& operator=(UpgradeHolder&& rhs) noexcept {
std::swap(lock_, rhs.lock_);
return *this;
}
UpgradeHolder(const UpgradeHolder& rhs) = delete;
UpgradeHolder& operator=(const UpgradeHolder& rhs) = delete;
~UpgradeHolder() {
unlock();
}
void unlock() {
if (lock_) {
lock_->unlock_upgrade();
lock_ = nullptr;
}
}
private:
friend class WriteHolder;
friend class ReadHolder;
SharedMutexImpl* lock_;
};
class [[nodiscard]] WriteHolder {
WriteHolder() : lock_(nullptr) {
}
public:
explicit WriteHolder(SharedMutexImpl * lock) : lock_(lock) {
if (lock_) {
lock_->lock();
}
}
explicit WriteHolder(SharedMutexImpl & lock) : lock_(&lock) {
lock_->lock();
}
explicit WriteHolder(UpgradeHolder && upgrade) : lock_(upgrade.lock_) {
(static_cast<bool>(upgrade.lock_ != nullptr)
? void(0)
: __assert_fail("upgrade.lock_ != nullptr",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1483,
__extension__ __PRETTY_FUNCTION__));
upgrade.lock_ = nullptr;
lock_->unlock_upgrade_and_lock();
}
// # 1512 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
WriteHolder(WriteHolder && rhs) noexcept : lock_(rhs.lock_) {
rhs.lock_ = nullptr;
}
WriteHolder& operator=(WriteHolder&& rhs) noexcept {
std::swap(lock_, rhs.lock_);
return *this;
}
WriteHolder(const WriteHolder& rhs) = delete;
WriteHolder& operator=(const WriteHolder& rhs) = delete;
~WriteHolder() {
unlock();
}
void unlock() {
if (lock_) {
lock_->unlock();
lock_ = nullptr;
}
}
private:
friend class ReadHolder;
friend class UpgradeHolder;
SharedMutexImpl* lock_;
};
friend void acquireRead(SharedMutexImpl& lock) {
lock.lock_shared();
}
friend void acquireReadWrite(SharedMutexImpl& lock) {
lock.lock();
}
friend void releaseRead(SharedMutexImpl& lock) {
lock.unlock_shared();
}
friend void releaseReadWrite(SharedMutexImpl& lock) {
lock.unlock();
}
friend bool acquireRead(SharedMutexImpl& lock, unsigned int ms) {
return lock.try_lock_shared_for(std::chrono::milliseconds(ms));
}
friend bool acquireReadWrite(SharedMutexImpl& lock, unsigned int ms) {
return lock.try_lock_for(std::chrono::milliseconds(ms));
}
};
typedef SharedMutexImpl<true> SharedMutexReadPriority;
typedef SharedMutexImpl<false> SharedMutexWritePriority;
typedef SharedMutexWritePriority SharedMutex;
typedef SharedMutexImpl<false, void, std::atomic, false, false>
SharedMutexSuppressTSAN;
extern template class SharedMutexImpl<true>;
extern template class SharedMutexImpl<false>;
template <bool ReaderPriority,
typename Tag_,
template <typename>
class Atom,
bool BlockImmediately,
bool AnnotateForThreadSanitizer>
alignas(hardware_destructive_interference_size)
typename SharedMutexImpl<ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::DeferredReaderSlot
SharedMutexImpl<ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::deferredReaders
[shared_mutex_detail::kMaxDeferredReadersAllocated *
kDeferredSeparationFactor] = {};
template <bool ReaderPriority,
typename Tag_,
template <typename>
class Atom,
bool BlockImmediately,
bool AnnotateForThreadSanitizer>
__thread uint32_t
SharedMutexImpl<ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::tls_lastTokenlessSlot = 0;
template <bool ReaderPriority,
typename Tag_,
template <typename>
class Atom,
bool BlockImmediately,
bool AnnotateForThreadSanitizer>
__thread uint32_t SharedMutexImpl<
ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::tls_lastDeferredReaderSlot = 0;
template <bool ReaderPriority,
typename Tag_,
template <typename>
class Atom,
bool BlockImmediately,
bool AnnotateForThreadSanitizer>
bool SharedMutexImpl<
ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::tryUnlockTokenlessSharedDeferred() {
auto bestSlot = make_atomic_ref(tls_lastTokenlessSlot)
.load(std::memory_order_relaxed);
uint32_t i = 0;
do {
auto slotPtr = deferredReader(bestSlot ^ i);
auto slotValue = slotPtr->load(std::memory_order_relaxed);
if (slotValue == tokenlessSlotValue() &&
slotPtr->compare_exchange_strong(slotValue, 0)) {
make_atomic_ref(tls_lastTokenlessSlot)
.store(bestSlot ^ i, std::memory_order_relaxed);
return true;
}
++i;
} while (i < shared_mutex_detail::getMaxDeferredReaders());
return false;
}
template <bool ReaderPriority,
typename Tag_,
template <typename>
class Atom,
bool BlockImmediately,
bool AnnotateForThreadSanitizer>
template <class WaitContext>
bool SharedMutexImpl<
ReaderPriority,
Tag_,
Atom,
BlockImmediately,
AnnotateForThreadSanitizer>::lockSharedImpl(uint32_t& state,
Token* token,
WaitContext& ctx) {
const uint32_t maxDeferredReaders =
shared_mutex_detail::getMaxDeferredReaders();
while (true) {
if ((__builtin_expect(((state & kHasE) != 0), 0)) &&
!waitForZeroBits(state, kHasE, kWaitingS, ctx) &&
ctx.canTimeOut()) {
return false;
}
uint32_t slot = make_atomic_ref(tls_lastDeferredReaderSlot)
.load(std::memory_order_relaxed);
uintptr_t slotValue = 1;
bool canAlreadyDefer = (state & kMayDefer) != 0;
bool aboveDeferThreshold =
(state & kHasS) >= (kNumSharedToStartDeferring - 1) * kIncrHasS;
bool drainInProgress = ReaderPriority && (state & kBegunE) != 0;
if (canAlreadyDefer || (aboveDeferThreshold && !drainInProgress)) {
slotValue = deferredReader(slot)->load(std::memory_order_relaxed);
if (slotValue != 0) {
uint32_t bestSlot =
(uint32_t)folly::AccessSpreader<Atom>::current(
maxDeferredReaders);
for (uint32_t i = 0; i < kDeferredSearchDistance; ++i) {
slot = bestSlot ^ i;
(static_cast<bool>(slot < maxDeferredReaders)
? void(0)
: __assert_fail(
"slot < maxDeferredReaders",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1694,
__extension__ __PRETTY_FUNCTION__));
slotValue = deferredReader(slot)->load(
std::memory_order_relaxed);
if (slotValue == 0) {
make_atomic_ref(tls_lastDeferredReaderSlot)
.store(slot, std::memory_order_relaxed);
break;
}
}
}
}
if (slotValue != 0) {
if (state_.compare_exchange_strong(state, state + kIncrHasS)) {
if (token != nullptr) {
token->type_ = Token::Type::INLINE_SHARED;
}
return true;
}
continue;
}
if ((state & kMayDefer) == 0) {
if (!state_.compare_exchange_strong(state, state | kMayDefer)) {
if ((state & (kHasE | kMayDefer)) != kMayDefer) {
continue;
}
}
}
bool gotSlot = deferredReader(slot)->compare_exchange_strong(
slotValue,
token == nullptr ? tokenlessSlotValue() : tokenfulSlotValue());
// # 1743 "tlm/deps/folly.exploded/include/folly/SharedMutex.h" 3 4
state = state_.load(std::memory_order_acquire);
if (!gotSlot) {
continue;
}
if (token == nullptr) {
make_atomic_ref(tls_lastTokenlessSlot)
.store(slot, std::memory_order_relaxed);
}
if ((state & kMayDefer) != 0) {
(static_cast<bool>((state & kHasE) == 0)
? void(0)
: __assert_fail("(state & kHasE) == 0",
"tlm/deps/folly.exploded/include/folly/"
"SharedMutex.h",
1755,
__extension__ __PRETTY_FUNCTION__));
if (token != nullptr) {
token->type_ = Token::Type::DEFERRED_SHARED;
token->slot_ = (uint16_t)slot;
}
return true;
}
if (token == nullptr) {
if (!tryUnlockTokenlessSharedDeferred()) {
unlockSharedInline();
}
} else {
if (!tryUnlockSharedDeferred(slot)) {
unlockSharedInline();
}
}
}
}
} // namespace folly
// # 52 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 28 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
// # 1 "tlm/deps/glog.exploded/include/glog/logging.h" 1 3 4
// # 44 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
// # 45 "tlm/deps/glog.exploded/include/glog/logging.h" 2 3 4
// # 89 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace google {
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
// # 110 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
} // namespace google
// # 334 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace fLB {
extern bool FLAGS_logtostderr;
}
using fLB::FLAGS_logtostderr;
namespace fLB {
extern bool FLAGS_alsologtostderr;
}
using fLB::FLAGS_alsologtostderr;
namespace fLB {
extern bool FLAGS_colorlogtostderr;
}
using fLB::FLAGS_colorlogtostderr;
namespace fLI {
extern google::int32 FLAGS_stderrthreshold;
}
using fLI::FLAGS_stderrthreshold;
namespace fLB {
extern bool FLAGS_log_prefix;
}
using fLB::FLAGS_log_prefix;
namespace fLI {
extern google::int32 FLAGS_logbuflevel;
}
using fLI::FLAGS_logbuflevel;
namespace fLI {
extern google::int32 FLAGS_logbufsecs;
}
using fLI::FLAGS_logbufsecs;
namespace fLI {
extern google::int32 FLAGS_minloglevel;
}
using fLI::FLAGS_minloglevel;
namespace fLS {
extern std::string& FLAGS_log_dir;
}
using fLS::FLAGS_log_dir;
namespace fLI {
extern google::int32 FLAGS_logfile_mode;
}
using fLI::FLAGS_logfile_mode;
namespace fLS {
extern std::string& FLAGS_log_link;
}
using fLS::FLAGS_log_link;
namespace fLI {
extern google::int32 FLAGS_v;
}
using fLI::FLAGS_v;
namespace fLI {
extern google::int32 FLAGS_max_log_size;
}
using fLI::FLAGS_max_log_size;
namespace fLB {
extern bool FLAGS_stop_logging_if_full_disk;
}
using fLB::FLAGS_stop_logging_if_full_disk;
// # 509 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace google {
// # 1 "tlm/deps/glog.exploded/include/glog/log_severity.h" 1 3 4
// # 45 "tlm/deps/glog.exploded/include/glog/log_severity.h" 3 4
typedef int LogSeverity;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
// # 64 "tlm/deps/glog.exploded/include/glog/log_severity.h" 3 4
extern const char* const LogSeverityNames[NUM_SEVERITIES];
// # 88 "tlm/deps/glog.exploded/include/glog/log_severity.h" 3 4
enum { DEBUG_MODE = 1 };
// # 513 "tlm/deps/glog.exploded/include/glog/logging.h" 2 3 4
// # 1 "tlm/deps/glog.exploded/include/glog/vlog_is_on.h" 1 3 4
// # 104 "tlm/deps/glog.exploded/include/glog/vlog_is_on.h" 3 4
extern int SetVLOGLevel(const char* module_pattern, int log_level);
extern google::int32 kLogSiteUninitialized;
// # 123 "tlm/deps/glog.exploded/include/glog/vlog_is_on.h" 3 4
extern bool InitVLOG3__(google::int32** site_flag,
google::int32* site_default,
const char* fname,
google::int32 verbose_level);
// # 514 "tlm/deps/glog.exploded/include/glog/logging.h" 2 3 4
void InitGoogleLogging(const char* argv0);
void ShutdownGoogleLogging();
void InstallFailureFunction(void (*fail_func)());
class LogSink;
// # 592 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
struct CheckOpString {
CheckOpString(std::string* str) : str_(str) {
}
operator bool() const {
return (__builtin_expect(str_ != __null, 0));
}
std::string* str_;
};
template <class T>
inline const T& GetReferenceableValue(const T& t) {
return t;
}
inline char GetReferenceableValue(char t) {
return t;
}
inline unsigned char GetReferenceableValue(unsigned char t) {
return t;
}
inline signed char GetReferenceableValue(signed char t) {
return t;
}
inline short GetReferenceableValue(short t) {
return t;
}
inline unsigned short GetReferenceableValue(unsigned short t) {
return t;
}
inline int GetReferenceableValue(int t) {
return t;
}
inline unsigned int GetReferenceableValue(unsigned int t) {
return t;
}
inline long GetReferenceableValue(long t) {
return t;
}
inline unsigned long GetReferenceableValue(unsigned long t) {
return t;
}
inline long long GetReferenceableValue(long long t) {
return t;
}
inline unsigned long long GetReferenceableValue(unsigned long long t) {
return t;
}
struct DummyClassToDefineOperator {};
} // namespace google
inline std::ostream& operator<<(std::ostream& out,
const google::DummyClassToDefineOperator&) {
return out;
}
namespace google {
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
template <>
void MakeCheckOpValueString(std::ostream* os, const char& v);
template <>
void MakeCheckOpValueString(std::ostream* os, const signed char& v);
template <>
void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
__attribute__((noinline));
namespace base {
namespace internal {
LogSeverity NormalizeSeverity(LogSeverity s);
}
class CheckOpMessageBuilder {
public:
explicit CheckOpMessageBuilder(const char* exprtext);
~CheckOpMessageBuilder();
std::ostream* ForVar1() {
return stream_;
}
std::ostream* ForVar2();
std::string* NewString();
private:
std::ostringstream* stream_;
};
} // namespace base
template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1,
const T2& v2,
const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// # 719 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
template <typename T1, typename T2>
inline std::string* Check_EQImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 == v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_EQImpl(int v1, int v2, const char* exprtext) {
return Check_EQImpl<int, int>(v1, v2, exprtext);
}
template <typename T1, typename T2>
inline std::string* Check_NEImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 != v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_NEImpl(int v1, int v2, const char* exprtext) {
return Check_NEImpl<int, int>(v1, v2, exprtext);
}
template <typename T1, typename T2>
inline std::string* Check_LEImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 <= v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_LEImpl(int v1, int v2, const char* exprtext) {
return Check_LEImpl<int, int>(v1, v2, exprtext);
}
template <typename T1, typename T2>
inline std::string* Check_LTImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 < v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_LTImpl(int v1, int v2, const char* exprtext) {
return Check_LTImpl<int, int>(v1, v2, exprtext);
}
template <typename T1, typename T2>
inline std::string* Check_GEImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 >= v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_GEImpl(int v1, int v2, const char* exprtext) {
return Check_GEImpl<int, int>(v1, v2, exprtext);
}
template <typename T1, typename T2>
inline std::string* Check_GTImpl(const T1& v1,
const T2& v2,
const char* exprtext) {
if ((__builtin_expect(!!(v1 > v2), 1)))
return __null;
else
return MakeCheckOpString(v1, v2, exprtext);
}
inline std::string* Check_GTImpl(int v1, int v2, const char* exprtext) {
return Check_GTImpl<int, int>(v1, v2, exprtext);
}
// # 743 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
typedef std::string _Check_string;
// # 808 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
std::string* CheckstrcmptrueImpl(const char* s1,
const char* s2,
const char* names);
std::string* CheckstrcmpfalseImpl(const char* s1,
const char* s2,
const char* names);
std::string* CheckstrcasecmptrueImpl(const char* s1,
const char* s2,
const char* names);
std::string* CheckstrcasecmpfalseImpl(const char* s1,
const char* s2,
const char* names);
// # 930 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace glog_internal_namespace_ {
template <bool>
struct CompileAssert {};
struct CrashReason;
bool IsFailureSignalHandlerInstalled();
} // namespace glog_internal_namespace_
// # 957 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
enum PRIVATE_Counter { COUNTER };
// # 968 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
const LogSeverity GLOG_0 = GLOG_ERROR;
// # 1109 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace base_logging {
class LogStreamBuf : public std::streambuf {
public:
LogStreamBuf(char* buf, int len) {
setp(buf, buf + len - 2);
}
virtual int_type overflow(int_type ch) {
return ch;
}
size_t pcount() const {
return pptr() - pbase();
}
char* pbase() const {
return std::streambuf::pbase();
}
};
} // namespace base_logging
// # 1142 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
class LogMessage {
public:
enum {
kNoLogPrefix = -1
};
class LogStream : public std::ostream {
public:
LogStream(char* buf, int len, int ctr)
: std::ostream(__null),
streambuf_(buf, len),
ctr_(ctr),
self_(this) {
rdbuf(&streambuf_);
}
int ctr() const {
return ctr_;
}
void set_ctr(int ctr) {
ctr_ = ctr;
}
LogStream* self() const {
return self_;
}
size_t pcount() const {
return streambuf_.pcount();
}
char* pbase() const {
return streambuf_.pbase();
}
char* str() const {
return pbase();
}
private:
LogStream(const LogStream&);
LogStream& operator=(const LogStream&);
base_logging::LogStreamBuf streambuf_;
int ctr_;
LogStream* self_;
};
public:
typedef void (LogMessage::*SendMethod)();
LogMessage(const char* file,
int line,
LogSeverity severity,
int ctr,
SendMethod send_method);
// # 1203 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
LogMessage(const char* file, int line);
LogMessage(const char* file, int line, LogSeverity severity);
LogMessage(const char* file,
int line,
LogSeverity severity,
LogSink* sink,
bool also_send_to_log);
LogMessage(const char* file,
int line,
LogSeverity severity,
std::vector<std::string>* outvec);
LogMessage(const char* file,
int line,
LogSeverity severity,
std::string* message);
LogMessage(const char* file, int line, const CheckOpString& result);
~LogMessage();
void Flush();
static const size_t kMaxLogMessageLen;
void SendToLog();
void SendToSyslogAndLog();
static void __attribute__((noreturn)) Fail();
std::ostream& stream();
int preserved_errno() const;
static int64 num_messages(int severity);
struct LogMessageData;
private:
void SendToSinkAndLog();
void SendToSink();
void WriteToStringAndLog();
void SaveOrSendToLog();
void Init(const char* file,
int line,
LogSeverity severity,
void (LogMessage::*send_method)());
void RecordCrashReason(glog_internal_namespace_::CrashReason* reason);
static int64 num_messages_[NUM_SEVERITIES];
LogMessageData* allocated_;
LogMessageData* data_;
friend class LogDestination;
LogMessage(const LogMessage&);
void operator=(const LogMessage&);
};
class LogMessageFatal : public LogMessage {
public:
LogMessageFatal(const char* file, int line);
LogMessageFatal(const char* file, int line, const CheckOpString& result);
__attribute__((noreturn)) ~LogMessageFatal();
};
inline void LogAtLevel(int const severity, std::string const& msg) {
LogMessage("tlm/deps/glog.exploded/include/glog/logging.h", 1304, severity)
.stream()
<< msg;
}
// # 1332 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
template <typename T>
T CheckNotNull(const char* file, int line, const char* names, T&& t) {
if (t == nullptr) {
LogMessageFatal(file, line, new std::string(names));
}
return std::forward<T>(t);
}
// # 1355 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
std::ostream& operator<<(std::ostream& os, const PRIVATE_Counter&);
class ErrnoLogMessage : public LogMessage {
public:
ErrnoLogMessage(const char* file,
int line,
LogSeverity severity,
int ctr,
void (LogMessage::*send_method)());
~ErrnoLogMessage();
private:
ErrnoLogMessage(const ErrnoLogMessage&);
void operator=(const ErrnoLogMessage&);
};
class LogMessageVoidify {
public:
LogMessageVoidify() {
}
void operator&(std::ostream&) {
}
};
void FlushLogFiles(LogSeverity min_severity);
void FlushLogFilesUnsafe(LogSeverity min_severity);
void SetLogDestination(LogSeverity severity, const char* base_filename);
void SetLogSymlink(LogSeverity severity, const char* symlink_basename);
class LogSink {
public:
virtual ~LogSink();
virtual void send(LogSeverity severity,
const char* full_filename,
const char* base_filename,
int line,
const struct ::tm* tm_time,
const char* message,
size_t message_len) = 0;
// # 1444 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
virtual void WaitTillSent();
static std::string ToString(LogSeverity severity,
const char* file,
int line,
const struct ::tm* tm_time,
const char* message,
size_t message_len);
};
void AddLogSink(LogSink* destination);
void RemoveLogSink(LogSink* destination);
void SetLogFilenameExtension(const char* filename_extension);
void SetStderrLogging(LogSeverity min_severity);
void LogToStderr();
void SetEmailLogging(LogSeverity min_severity, const char* addresses);
bool SendEmail(const char* dest, const char* subject, const char* body);
const std::vector<std::string>& GetLoggingDirectories();
void TestOnly_ClearLoggingDirectoriesList();
void GetExistingTempDirectories(std::vector<std::string>* list);
void ReprintFatalMessage();
// # 1517 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
void TruncateLogFile(const char* path, int64 limit, int64 keep);
void TruncateStdoutStderr();
const char* GetLogSeverityName(LogSeverity severity);
// # 1540 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
namespace base {
class Logger {
public:
virtual ~Logger();
// # 1554 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
virtual void Write(bool force_flush,
time_t timestamp,
const char* message,
int message_len) = 0;
virtual void Flush() = 0;
virtual uint32 LogSize() = 0;
};
extern Logger* GetLogger(LogSeverity level);
extern void SetLogger(LogSeverity level, Logger* logger);
} // namespace base
// # 1591 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
int posix_strerror_r(int err, char* buf, size_t len);
std::string StrError(int err);
class NullStream : public LogMessage::LogStream {
public:
NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) {
}
NullStream(const char*, int, const CheckOpString&)
: LogMessage::LogStream(message_buffer_, 1, 0) {
}
NullStream& stream() {
return *this;
}
private:
char message_buffer_[2];
};
template <class T>
inline NullStream& operator<<(NullStream& str, const T&) {
return str;
}
class NullStreamFatal : public NullStream {
public:
NullStreamFatal() {
}
NullStreamFatal(const char* file, int line, const CheckOpString& result)
: NullStream(file, line, result) {
}
__attribute__((noreturn)) ~NullStreamFatal() throw() {
_exit(1);
}
};
// # 1651 "tlm/deps/glog.exploded/include/glog/logging.h" 3 4
void InstallFailureSignalHandler();
void InstallFailureWriter(void (*writer)(const char* data, int size));
} // namespace google
// # 29 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Exception.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Exception.h" 3 4
// # 22 "tlm/deps/folly.exploded/include/folly/Exception.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Conv.h" 1 3 4
// # 100 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
// # 104 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 105 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 106 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 114 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
// # 1
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 1 3 4 # 31
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4 # 1
// "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h" 1 3 4
// # 31 "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h"
// 3 4 # 32
// "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h" 2 3 4
// # 35 "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h"
// 2 3 4 # 119
// "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h" 3 4
typedef uint16_t uc16;
// # 157 "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h"
// 3 4
namespace double_conversion {
static const int kCharSize = sizeof(char);
template <typename T>
static T Max(T a, T b) {
return a < b ? b : a;
}
template <typename T>
static T Min(T a, T b) {
return a < b ? a : b;
}
inline int StrLength(const char* string) {
size_t length = strlen(string);
(static_cast<bool>(length == static_cast<size_t>(static_cast<int>(length)))
? void(0)
: __assert_fail("length == "
"static_cast<size_t>(static_cast<int>(length))",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
177,
__extension__ __PRETTY_FUNCTION__));
;
return static_cast<int>(length);
}
template <typename T>
class Vector {
public:
Vector() : start_(__null), length_(0) {
}
Vector(T* data, int len) : start_(data), length_(len) {
(static_cast<bool>(len == 0 || (len > 0 && data != __null))
? void(0)
: __assert_fail("len == 0 || (len > 0 && data != __null)",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
187,
__extension__ __PRETTY_FUNCTION__));
;
}
Vector<T> SubVector(int from, int to) {
(static_cast<bool>(to <= length_)
? void(0)
: __assert_fail("to <= length_",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
193,
__extension__ __PRETTY_FUNCTION__));
;
(static_cast<bool>(from < to)
? void(0)
: __assert_fail("from < to",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
194,
__extension__ __PRETTY_FUNCTION__));
;
(static_cast<bool>(0 <= from)
? void(0)
: __assert_fail("0 <= from",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
195,
__extension__ __PRETTY_FUNCTION__));
;
return Vector<T>(start() + from, to - from);
}
int length() const {
return length_;
}
bool is_empty() const {
return length_ == 0;
}
T* start() const {
return start_;
}
T& operator[](int index) const {
(static_cast<bool>(0 <= index && index < length_)
? void(0)
: __assert_fail("0 <= index && index < length_",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
210,
__extension__ __PRETTY_FUNCTION__));
;
return start_[index];
}
T& first() {
return start_[0];
}
T& last() {
return start_[length_ - 1];
}
private:
T* start_;
int length_;
};
class StringBuilder {
public:
StringBuilder(char* buffer, int buffer_size)
: buffer_(buffer, buffer_size), position_(0) {
}
~StringBuilder() {
if (!is_finalized())
Finalize();
}
int size() const {
return buffer_.length();
}
int position() const {
(static_cast<bool>(!is_finalized())
? void(0)
: __assert_fail("!is_finalized()",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
238,
__extension__ __PRETTY_FUNCTION__));
;
return position_;
}
void Reset() {
position_ = 0;
}
void AddCharacter(char c) {
(static_cast<bool>(c != '\0')
? void(0)
: __assert_fail("c != '\\0'",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
249,
__extension__ __PRETTY_FUNCTION__));
;
(static_cast<bool>(!is_finalized() && position_ < buffer_.length())
? void(0)
: __assert_fail(
"!is_finalized() && position_ < buffer_.length()",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
250,
__extension__ __PRETTY_FUNCTION__));
;
buffer_[position_++] = c;
}
void AddString(const char* s) {
AddSubstring(s, StrLength(s));
}
void AddSubstring(const char* s, int n) {
(static_cast<bool>(!is_finalized() && position_ + n < buffer_.length())
? void(0)
: __assert_fail("!is_finalized() && position_ + n < "
"buffer_.length()",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
263,
__extension__ __PRETTY_FUNCTION__));
;
(static_cast<bool>(static_cast<size_t>(n) <= strlen(s))
? void(0)
: __assert_fail("static_cast<size_t>(n) <= strlen(s)",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
264,
__extension__ __PRETTY_FUNCTION__));
;
memmove(&buffer_[position_], s, n * kCharSize);
position_ += n;
}
void AddPadding(char c, int count) {
for (int i = 0; i < count; i++) {
AddCharacter(c);
}
}
char* Finalize() {
(static_cast<bool>(!is_finalized() && position_ < buffer_.length())
? void(0)
: __assert_fail(
"!is_finalized() && position_ < buffer_.length()",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
280,
__extension__ __PRETTY_FUNCTION__));
;
buffer_[position_] = '\0';
(static_cast<bool>(strlen(buffer_.start()) ==
static_cast<size_t>(position_))
? void(0)
: __assert_fail("strlen(buffer_.start()) == "
"static_cast<size_t>(position_)",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
284,
__extension__ __PRETTY_FUNCTION__));
;
position_ = -1;
(static_cast<bool>(is_finalized())
? void(0)
: __assert_fail("is_finalized()",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/utils.h",
286,
__extension__ __PRETTY_FUNCTION__));
;
return buffer_.start();
}
private:
Vector<char> buffer_;
int position_;
bool is_finalized() const {
return position_ < 0;
}
StringBuilder();
StringBuilder(const StringBuilder&);
void operator=(const StringBuilder&);
};
// # 323 "tlm/deps/double-conversion.exploded/include/double-conversion/utils.h"
// 3 4
template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
__attribute__((unused)) typedef char
VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
Dest dest;
memmove(&dest, &source, sizeof(dest));
return dest;
}
template <class Dest, class Source>
inline Dest BitCast(Source* source) {
return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
}
} // namespace double_conversion
// # 32
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 2 3 4
namespace double_conversion {
class DoubleToStringConverter {
public:
static const int kMaxFixedDigitsBeforePoint = 60;
static const int kMaxFixedDigitsAfterPoint = 60;
static const int kMaxExponentialDigits = 120;
static const int kMinPrecisionDigits = 1;
static const int kMaxPrecisionDigits = 120;
enum Flags {
NO_FLAGS = 0,
EMIT_POSITIVE_EXPONENT_SIGN = 1,
EMIT_TRAILING_DECIMAL_POINT = 2,
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
UNIQUE_ZERO = 8
};
// # 107
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
DoubleToStringConverter(int flags,
const char* infinity_symbol,
const char* nan_symbol,
char exponent_character,
int decimal_in_shortest_low,
int decimal_in_shortest_high,
int max_leading_padding_zeroes_in_precision_mode,
int max_trailing_padding_zeroes_in_precision_mode)
: flags_(flags),
infinity_symbol_(infinity_symbol),
nan_symbol_(nan_symbol),
exponent_character_(exponent_character),
decimal_in_shortest_low_(decimal_in_shortest_low),
decimal_in_shortest_high_(decimal_in_shortest_high),
max_leading_padding_zeroes_in_precision_mode_(
max_leading_padding_zeroes_in_precision_mode),
max_trailing_padding_zeroes_in_precision_mode_(
max_trailing_padding_zeroes_in_precision_mode) {
(static_cast<bool>(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
!((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0))
? void(0)
: __assert_fail(
"((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || "
"!((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)",
"tlm/deps/double-conversion.exploded/include/"
"double-conversion/double-conversion.h",
127,
__extension__ __PRETTY_FUNCTION__));
;
}
static const DoubleToStringConverter& EcmaScriptConverter();
// # 157
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
bool ToShortest(double value, StringBuilder* result_builder) const {
return ToShortestIeeeNumber(value, result_builder, SHORTEST);
}
bool ToShortestSingle(float value, StringBuilder* result_builder) const {
return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
}
// # 200
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
bool ToFixed(double value,
int requested_digits,
StringBuilder* result_builder) const;
// # 232
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
bool ToExponential(double value,
int requested_digits,
StringBuilder* result_builder) const;
// # 270
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
bool ToPrecision(double value,
int precision,
StringBuilder* result_builder) const;
enum DtoaMode {
SHORTEST,
SHORTEST_SINGLE,
FIXED,
PRECISION
};
static const int kBase10MaximalLength = 17;
// # 335
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
static void DoubleToAscii(double v,
DtoaMode mode,
int requested_digits,
char* buffer,
int buffer_length,
bool* sign,
int* length,
int* point);
private:
bool ToShortestIeeeNumber(double value,
StringBuilder* result_builder,
DtoaMode mode) const;
bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
void CreateExponentialRepresentation(const char* decimal_digits,
int length,
int exponent,
StringBuilder* result_builder) const;
void CreateDecimalRepresentation(const char* decimal_digits,
int length,
int decimal_point,
int digits_after_point,
StringBuilder* result_builder) const;
const int flags_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
const char exponent_character_;
const int decimal_in_shortest_low_;
const int decimal_in_shortest_high_;
const int max_leading_padding_zeroes_in_precision_mode_;
const int max_trailing_padding_zeroes_in_precision_mode_;
DoubleToStringConverter();
DoubleToStringConverter(const DoubleToStringConverter&);
void operator=(const DoubleToStringConverter&);
};
class StringToDoubleConverter {
public:
enum Flags {
NO_FLAGS = 0,
ALLOW_HEX = 1,
ALLOW_OCTALS = 2,
ALLOW_TRAILING_JUNK = 4,
ALLOW_LEADING_SPACES = 8,
ALLOW_TRAILING_SPACES = 16,
ALLOW_SPACES_AFTER_SIGN = 32
};
// # 487
// "tlm/deps/double-conversion.exploded/include/double-conversion/double-conversion.h"
// 3 4
StringToDoubleConverter(int flags,
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
const char* nan_symbol)
: flags_(flags),
empty_string_value_(empty_string_value),
junk_string_value_(junk_string_value),
infinity_symbol_(infinity_symbol),
nan_symbol_(nan_symbol) {
}
double StringToDouble(const char* buffer,
int length,
int* processed_characters_count) const;
double StringToDouble(const uc16* buffer,
int length,
int* processed_characters_count) const;
float StringToFloat(const char* buffer,
int length,
int* processed_characters_count) const;
float StringToFloat(const uc16* buffer,
int length,
int* processed_characters_count) const;
private:
const int flags_;
const double empty_string_value_;
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
template <class Iterator>
double StringToIeee(Iterator start_pointer,
int length,
bool read_as_double,
int* processed_characters_count) const;
StringToDoubleConverter();
StringToDoubleConverter(const StringToDoubleConverter&);
void operator=(const StringToDoubleConverter&);
};
} // namespace double_conversion
// # 115 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Demangle.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Demangle.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/FBString.h" 1 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
// # 39 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
// # 40 "tlm/deps/folly.exploded/include/folly/FBString.h" 2 3 4
// # 41 "tlm/deps/folly.exploded/include/folly/FBString.h" 2 3 4
// # 50 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
// # 50 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
#pragma GCC diagnostic push
// # 50 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
// # 52 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
#pragma GCC diagnostic ignored "-Wshadow"
// # 52 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
namespace folly {
// # 68 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
namespace fbstring_detail {
template <class InIt, class OutIt>
inline std::pair<InIt, OutIt> copy_n(
InIt b,
typename std::iterator_traits<InIt>::difference_type n,
OutIt d) {
for (; n != 0; --n, ++b, ++d) {
*d = *b;
}
return std::make_pair(b, d);
}
template <class Pod, class T>
inline void podFill(Pod* b, Pod* e, T c) {
(static_cast<bool>(b && e && b <= e)
? void(0)
: __assert_fail("b && e && b <= e",
"tlm/deps/folly.exploded/include/folly/FBString.h",
83,
__extension__ __PRETTY_FUNCTION__));
constexpr auto kUseMemset = sizeof(T) == 1;
if (kUseMemset) {
memset(b, c, size_t(e - b));
} else {
auto const ee = b + ((e - b) & ~7u);
for (; b != ee; b += 8) {
b[0] = c;
b[1] = c;
b[2] = c;
b[3] = c;
b[4] = c;
b[5] = c;
b[6] = c;
b[7] = c;
}
for (; b != e; ++b) {
*b = c;
}
}
}
// # 114 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
template <class Pod>
inline void podCopy(const Pod* b, const Pod* e, Pod* d) {
(static_cast<bool>(b != nullptr)
? void(0)
: __assert_fail("b != nullptr",
"tlm/deps/folly.exploded/include/folly/FBString.h",
116,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(e != nullptr)
? void(0)
: __assert_fail("e != nullptr",
"tlm/deps/folly.exploded/include/folly/FBString.h",
117,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(d != nullptr)
? void(0)
: __assert_fail("d != nullptr",
"tlm/deps/folly.exploded/include/folly/FBString.h",
118,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(e >= b)
? void(0)
: __assert_fail("e >= b",
"tlm/deps/folly.exploded/include/folly/FBString.h",
119,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(d >= e || d + (e - b) <= b)
? void(0)
: __assert_fail("d >= e || d + (e - b) <= b",
"tlm/deps/folly.exploded/include/folly/FBString.h",
120,
__extension__ __PRETTY_FUNCTION__));
memcpy(d, b, (e - b) * sizeof(Pod));
}
template <class Pod>
inline void podMove(const Pod* b, const Pod* e, Pod* d) {
(static_cast<bool>(e >= b)
? void(0)
: __assert_fail("e >= b",
"tlm/deps/folly.exploded/include/folly/FBString.h",
130,
__extension__ __PRETTY_FUNCTION__));
memmove(d, b, (e - b) * sizeof(*b));
}
} // namespace fbstring_detail
enum class AcquireMallocatedString {};
// # 244 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
template <class Char>
class fbstring_core {
public:
fbstring_core() noexcept {
reset();
}
fbstring_core(const fbstring_core& rhs) {
(static_cast<bool>(&rhs != this)
? void(0)
: __assert_fail(
"&rhs != this",
"tlm/deps/folly.exploded/include/folly/FBString.h",
252,
__extension__ __PRETTY_FUNCTION__));
switch (rhs.category()) {
case Category::isSmall:
copySmall(rhs);
break;
case Category::isMedium:
copyMedium(rhs);
break;
case Category::isLarge:
copyLarge(rhs);
break;
default:
folly::assume_unreachable();
}
(static_cast<bool>(size() == rhs.size())
? void(0)
: __assert_fail(
"size() == rhs.size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
266,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(memcmp(data(), rhs.data(), size() * sizeof(Char)) ==
0)
? void(0)
: __assert_fail(
"memcmp(data(), rhs.data(), size() * sizeof(Char)) "
"== 0",
"tlm/deps/folly.exploded/include/folly/FBString.h",
267,
__extension__ __PRETTY_FUNCTION__));
}
fbstring_core& operator=(const fbstring_core& rhs) = delete;
fbstring_core(fbstring_core&& goner) noexcept {
ml_ = goner.ml_;
goner.reset();
}
fbstring_core(const Char* const data,
const size_t size,
bool disableSSO = false) {
if (!disableSSO && size <= maxSmallSize) {
initSmall(data, size);
} else if (size <= maxMediumSize) {
initMedium(data, size);
} else {
initLarge(data, size);
}
(static_cast<bool>(this->size() == size)
? void(0)
: __assert_fail(
"this->size() == size",
"tlm/deps/folly.exploded/include/folly/FBString.h",
290,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(size == 0 ||
memcmp(this->data(), data, size * sizeof(Char)) == 0)
? void(0)
: __assert_fail(
"size == 0 || memcmp(this->data(), data, size * "
"sizeof(Char)) == 0",
"tlm/deps/folly.exploded/include/folly/FBString.h",
291,
__extension__ __PRETTY_FUNCTION__));
}
~fbstring_core() noexcept {
if (category() == Category::isSmall) {
return;
}
destroyMediumLarge();
}
// # 308 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
fbstring_core(Char* const data,
const size_t size,
const size_t allocatedSize,
AcquireMallocatedString) {
if (size > 0) {
(static_cast<bool>(allocatedSize >= size + 1)
? void(0)
: __assert_fail("allocatedSize >= size + 1",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
314,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(data[size] == '\0')
? void(0)
: __assert_fail("data[size] == '\\0'",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
315,
__extension__ __PRETTY_FUNCTION__));
ml_.data_ = data;
ml_.size_ = size;
ml_.setCapacity(allocatedSize - 1, Category::isMedium);
} else {
free(data);
reset();
}
}
void swap(fbstring_core& rhs) {
auto const t = ml_;
ml_ = rhs.ml_;
rhs.ml_ = t;
}
const Char* data() const {
return c_str();
}
Char* data() {
return c_str();
}
Char* mutableData() {
switch (category()) {
case Category::isSmall:
return small_;
case Category::isMedium:
return ml_.data_;
case Category::isLarge:
return mutableDataLarge();
}
folly::assume_unreachable();
}
const Char* c_str() const {
const Char* ptr = ml_.data_;
ptr = (category() == Category::isSmall) ? small_ : ptr;
return ptr;
}
void shrink(const size_t delta) {
if (category() == Category::isSmall) {
shrinkSmall(delta);
} else if (category() == Category::isMedium ||
RefCounted::refs(ml_.data_) == 1) {
shrinkMedium(delta);
} else {
shrinkLarge(delta);
}
}
__attribute__((__noinline__)) void reserve(size_t minCapacity,
bool disableSSO = false) {
switch (category()) {
case Category::isSmall:
reserveSmall(minCapacity, disableSSO);
break;
case Category::isMedium:
reserveMedium(minCapacity);
break;
case Category::isLarge:
reserveLarge(minCapacity);
break;
default:
folly::assume_unreachable();
}
(static_cast<bool>(capacity() >= minCapacity)
? void(0)
: __assert_fail(
"capacity() >= minCapacity",
"tlm/deps/folly.exploded/include/folly/FBString.h",
392,
__extension__ __PRETTY_FUNCTION__));
}
Char* expandNoinit(const size_t delta,
bool expGrowth = false,
bool disableSSO = false);
void push_back(Char c) {
*expandNoinit(1, true) = c;
}
size_t size() const {
size_t ret = ml_.size_;
if (kIsLittleEndian) {
typedef typename std::make_unsigned<Char>::type UChar;
auto maybeSmallSize =
size_t(maxSmallSize) -
size_t(static_cast<UChar>(small_[maxSmallSize]));
ret = (static_cast<ssize_t>(maybeSmallSize) >= 0) ? maybeSmallSize
: ret;
} else {
ret = (category() == Category::isSmall) ? smallSize() : ret;
}
return ret;
}
size_t capacity() const {
switch (category()) {
case Category::isSmall:
return maxSmallSize;
case Category::isLarge:
if (RefCounted::refs(ml_.data_) > 1) {
return ml_.size_;
}
break;
case Category::isMedium:
default:
break;
}
return ml_.capacity();
}
bool isShared() const {
return category() == Category::isLarge &&
RefCounted::refs(ml_.data_) > 1;
}
private:
Char* c_str() {
Char* ptr = ml_.data_;
ptr = (category() == Category::isSmall) ? small_ : ptr;
return ptr;
}
void reset() {
setSmallSize(0);
}
__attribute__((__noinline__)) void destroyMediumLarge() noexcept {
auto const c = category();
(static_cast<bool>(c != Category::isSmall)
? void(0)
: __assert_fail(
"c != Category::isSmall",
"tlm/deps/folly.exploded/include/folly/FBString.h",
457,
__extension__ __PRETTY_FUNCTION__));
if (c == Category::isMedium) {
free(ml_.data_);
} else {
RefCounted::decrementRefs(ml_.data_);
}
}
struct RefCounted {
std::atomic<size_t> refCount_;
Char data_[1];
constexpr static size_t getDataOffset() {
return __builtin_offsetof(RefCounted, data_);
}
static RefCounted* fromData(Char* p) {
return static_cast<RefCounted*>(static_cast<void*>(
static_cast<unsigned char*>(static_cast<void*>(p)) -
getDataOffset()));
}
static size_t refs(Char* p) {
return fromData(p)->refCount_.load(std::memory_order_acquire);
}
static void incrementRefs(Char* p) {
fromData(p)->refCount_.fetch_add(1, std::memory_order_acq_rel);
}
static void decrementRefs(Char* p) {
auto const dis = fromData(p);
size_t oldcnt =
dis->refCount_.fetch_sub(1, std::memory_order_acq_rel);
(static_cast<bool>(oldcnt > 0)
? void(0)
: __assert_fail("oldcnt > 0",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
490,
__extension__ __PRETTY_FUNCTION__));
if (oldcnt == 1) {
free(dis);
}
}
static RefCounted* create(size_t* size) {
const size_t allocSize = goodMallocSize(getDataOffset() +
(*size + 1) * sizeof(Char));
auto result = static_cast<RefCounted*>(checkedMalloc(allocSize));
result->refCount_.store(1, std::memory_order_release);
*size = (allocSize - getDataOffset()) / sizeof(Char) - 1;
return result;
}
static RefCounted* create(const Char* data, size_t* size) {
const size_t effectiveSize = *size;
auto result = create(size);
if ((__builtin_expect((effectiveSize > 0), 1))) {
fbstring_detail::podCopy(
data, data + effectiveSize, result->data_);
}
return result;
}
static RefCounted* reallocate(Char* const data,
const size_t currentSize,
const size_t currentCapacity,
size_t* newCapacity) {
(static_cast<bool>(*newCapacity > 0 && *newCapacity > currentSize)
? void(0)
: __assert_fail(
"*newCapacity > 0 && *newCapacity > currentSize",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
519,
__extension__ __PRETTY_FUNCTION__));
const size_t allocNewCapacity = goodMallocSize(
getDataOffset() + (*newCapacity + 1) * sizeof(Char));
auto const dis = fromData(data);
(static_cast<bool>(dis->refCount_.load(std::memory_order_acquire) ==
1)
? void(0)
: __assert_fail("dis->refCount_.load(std::memory_order_"
"acquire) == 1",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
523,
__extension__ __PRETTY_FUNCTION__));
auto result = static_cast<RefCounted*>(smartRealloc(
dis,
getDataOffset() + (currentSize + 1) * sizeof(Char),
getDataOffset() + (currentCapacity + 1) * sizeof(Char),
allocNewCapacity));
(static_cast<bool>(
result->refCount_.load(std::memory_order_acquire) == 1)
? void(0)
: __assert_fail("result->refCount_.load(std::memory_order_"
"acquire) == 1",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
529,
__extension__ __PRETTY_FUNCTION__));
*newCapacity =
(allocNewCapacity - getDataOffset()) / sizeof(Char) - 1;
return result;
}
};
typedef uint8_t category_type;
enum class Category : category_type {
isSmall = 0,
isMedium = kIsLittleEndian ? 0x80 : 0x2,
isLarge = kIsLittleEndian ? 0x40 : 0x1,
};
Category category() const {
return static_cast<Category>(bytes_[lastChar] & categoryExtractMask);
}
struct MediumLarge {
Char* data_;
size_t size_;
size_t capacity_;
size_t capacity() const {
return kIsLittleEndian ? capacity_ & capacityExtractMask
: capacity_ >> 2;
}
void setCapacity(size_t cap, Category cat) {
capacity_ = kIsLittleEndian ? cap | (static_cast<size_t>(cat)
<< kCategoryShift)
: (cap << 2) | static_cast<size_t>(cat);
}
};
union {
uint8_t bytes_[sizeof(MediumLarge)];
Char small_[sizeof(MediumLarge) / sizeof(Char)];
MediumLarge ml_;
};
constexpr static size_t lastChar = sizeof(MediumLarge) - 1;
constexpr static size_t maxSmallSize = lastChar / sizeof(Char);
constexpr static size_t maxMediumSize = 254 / sizeof(Char);
constexpr static uint8_t categoryExtractMask = kIsLittleEndian ? 0xC0 : 0x3;
constexpr static size_t kCategoryShift = (sizeof(size_t) - 1) * 8;
constexpr static size_t capacityExtractMask =
kIsLittleEndian ? ~(size_t(categoryExtractMask) << kCategoryShift)
: 0x0;
static_assert(!(sizeof(MediumLarge) % sizeof(Char)),
"Corrupt memory layout for fbstring.");
size_t smallSize() const {
(static_cast<bool>(category() == Category::isSmall)
? void(0)
: __assert_fail(
"category() == Category::isSmall",
"tlm/deps/folly.exploded/include/folly/FBString.h",
584,
__extension__ __PRETTY_FUNCTION__));
constexpr auto shift = kIsLittleEndian ? 0 : 2;
auto smallShifted = static_cast<size_t>(small_[maxSmallSize]) >> shift;
(static_cast<bool>(static_cast<size_t>(maxSmallSize) >= smallShifted)
? void(0)
: __assert_fail(
"static_cast<size_t>(maxSmallSize) >= smallShifted",
"tlm/deps/folly.exploded/include/folly/FBString.h",
587,
__extension__ __PRETTY_FUNCTION__));
return static_cast<size_t>(maxSmallSize) - smallShifted;
}
void setSmallSize(size_t s) {
(static_cast<bool>(s <= maxSmallSize)
? void(0)
: __assert_fail(
"s <= maxSmallSize",
"tlm/deps/folly.exploded/include/folly/FBString.h",
595,
__extension__ __PRETTY_FUNCTION__));
constexpr auto shift = kIsLittleEndian ? 0 : 2;
small_[maxSmallSize] = char((maxSmallSize - s) << shift);
small_[s] = '\0';
(static_cast<bool>(category() == Category::isSmall && size() == s)
? void(0)
: __assert_fail(
"category() == Category::isSmall && size() == s",
"tlm/deps/folly.exploded/include/folly/FBString.h",
599,
__extension__ __PRETTY_FUNCTION__));
}
void copySmall(const fbstring_core&);
void copyMedium(const fbstring_core&);
void copyLarge(const fbstring_core&);
void initSmall(const Char* data, size_t size);
void initMedium(const Char* data, size_t size);
void initLarge(const Char* data, size_t size);
void reserveSmall(size_t minCapacity, bool disableSSO);
void reserveMedium(size_t minCapacity);
void reserveLarge(size_t minCapacity);
void shrinkSmall(size_t delta);
void shrinkMedium(size_t delta);
void shrinkLarge(size_t delta);
void unshare(size_t minCapacity = 0);
Char* mutableDataLarge();
};
template <class Char>
inline void fbstring_core<Char>::copySmall(const fbstring_core& rhs) {
static_assert(__builtin_offsetof(MediumLarge, data_) == 0,
"fbstring layout failure");
static_assert(__builtin_offsetof(MediumLarge, size_) == sizeof(ml_.data_),
"fbstring layout failure");
static_assert(
__builtin_offsetof(MediumLarge, capacity_) == 2 * sizeof(ml_.data_),
"fbstring layout failure");
ml_ = rhs.ml_;
(static_cast<bool>(category() == Category::isSmall &&
this->size() == rhs.size())
? void(0)
: __assert_fail("category() == Category::isSmall && this->size() "
"== rhs.size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
637,
__extension__ __PRETTY_FUNCTION__));
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::copyMedium(
const fbstring_core& rhs) {
auto const allocSize = goodMallocSize((1 + rhs.ml_.size_) * sizeof(Char));
ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
fbstring_detail::podCopy(
rhs.ml_.data_, rhs.ml_.data_ + rhs.ml_.size_ + 1, ml_.data_);
ml_.size_ = rhs.ml_.size_;
ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
(static_cast<bool>(category() == Category::isMedium)
? void(0)
: __assert_fail("category() == Category::isMedium",
"tlm/deps/folly.exploded/include/folly/FBString.h",
652,
__extension__ __PRETTY_FUNCTION__));
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::copyLarge(
const fbstring_core& rhs) {
ml_ = rhs.ml_;
RefCounted::incrementRefs(ml_.data_);
(static_cast<bool>(category() == Category::isLarge && size() == rhs.size())
? void(0)
: __assert_fail("category() == Category::isLarge && size() == "
"rhs.size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
661,
__extension__ __PRETTY_FUNCTION__));
}
template <class Char>
inline void fbstring_core<Char>::initSmall(const Char* const data,
const size_t size) {
static_assert(sizeof(*this) == sizeof(Char*) + 2 * sizeof(size_t),
"fbstring has unexpected size");
static_assert(sizeof(Char*) == sizeof(size_t),
"fbstring size assumption violation");
static_assert((sizeof(size_t) & (sizeof(size_t) - 1)) == 0,
"fbstring size assumption violation");
if ((reinterpret_cast<size_t>(data) & (sizeof(size_t) - 1)) == 0) {
const size_t byteSize = size * sizeof(Char);
constexpr size_t wordWidth = sizeof(size_t);
switch ((byteSize + wordWidth - 1) / wordWidth) {
case 3:
ml_.capacity_ = reinterpret_cast<const size_t*>(data)[2];
[[fallthrough]];
case 2:
ml_.size_ = reinterpret_cast<const size_t*>(data)[1];
[[fallthrough]];
case 1:
ml_.data_ = *reinterpret_cast<Char**>(const_cast<Char*>(data));
[[fallthrough]];
case 0:
break;
}
} else
{
if (size != 0) {
fbstring_detail::podCopy(data, data + size, small_);
}
}
setSmallSize(size);
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::initMedium(
const Char* const data, const size_t size) {
auto const allocSize = goodMallocSize((1 + size) * sizeof(Char));
ml_.data_ = static_cast<Char*>(checkedMalloc(allocSize));
if ((__builtin_expect((size > 0), 1))) {
fbstring_detail::podCopy(data, data + size, ml_.data_);
}
ml_.size_ = size;
ml_.setCapacity(allocSize / sizeof(Char) - 1, Category::isMedium);
ml_.data_[size] = '\0';
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::initLarge(
const Char* const data, const size_t size) {
size_t effectiveCapacity = size;
auto const newRC = RefCounted::create(data, &effectiveCapacity);
ml_.data_ = newRC->data_;
ml_.size_ = size;
ml_.setCapacity(effectiveCapacity, Category::isLarge);
ml_.data_[size] = '\0';
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::unshare(
size_t minCapacity) {
(static_cast<bool>(category() == Category::isLarge)
? void(0)
: __assert_fail("category() == Category::isLarge",
"tlm/deps/folly.exploded/include/folly/FBString.h",
743,
__extension__ __PRETTY_FUNCTION__));
size_t effectiveCapacity = std::max(minCapacity, ml_.capacity());
auto const newRC = RefCounted::create(&effectiveCapacity);
(static_cast<bool>(effectiveCapacity >= ml_.capacity())
? void(0)
: __assert_fail("effectiveCapacity >= ml_.capacity()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
748,
__extension__ __PRETTY_FUNCTION__));
fbstring_detail::podCopy(
ml_.data_, ml_.data_ + ml_.size_ + 1, newRC->data_);
RefCounted::decrementRefs(ml_.data_);
ml_.data_ = newRC->data_;
ml_.setCapacity(effectiveCapacity, Category::isLarge);
}
template <class Char>
inline Char* fbstring_core<Char>::mutableDataLarge() {
(static_cast<bool>(category() == Category::isLarge)
? void(0)
: __assert_fail("category() == Category::isLarge",
"tlm/deps/folly.exploded/include/folly/FBString.h",
759,
__extension__ __PRETTY_FUNCTION__));
if (RefCounted::refs(ml_.data_) > 1) {
unshare();
}
return ml_.data_;
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::reserveLarge(
size_t minCapacity) {
(static_cast<bool>(category() == Category::isLarge)
? void(0)
: __assert_fail("category() == Category::isLarge",
"tlm/deps/folly.exploded/include/folly/FBString.h",
769,
__extension__ __PRETTY_FUNCTION__));
if (RefCounted::refs(ml_.data_) > 1) {
unshare(minCapacity);
} else {
if (minCapacity > ml_.capacity()) {
auto const newRC = RefCounted::reallocate(
ml_.data_, ml_.size_, ml_.capacity(), &minCapacity);
ml_.data_ = newRC->data_;
ml_.setCapacity(minCapacity, Category::isLarge);
}
(static_cast<bool>(capacity() >= minCapacity)
? void(0)
: __assert_fail(
"capacity() >= minCapacity",
"tlm/deps/folly.exploded/include/folly/FBString.h",
786,
__extension__ __PRETTY_FUNCTION__));
}
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::reserveMedium(
const size_t minCapacity) {
(static_cast<bool>(category() == Category::isMedium)
? void(0)
: __assert_fail("category() == Category::isMedium",
"tlm/deps/folly.exploded/include/folly/FBString.h",
793,
__extension__ __PRETTY_FUNCTION__));
if (minCapacity <= ml_.capacity()) {
return;
}
if (minCapacity <= maxMediumSize) {
size_t capacityBytes = goodMallocSize((1 + minCapacity) * sizeof(Char));
ml_.data_ = static_cast<Char*>(
smartRealloc(ml_.data_,
(ml_.size_ + 1) * sizeof(Char),
(ml_.capacity() + 1) * sizeof(Char),
capacityBytes));
ml_.setCapacity(capacityBytes / sizeof(Char) - 1, Category::isMedium);
} else {
fbstring_core nascent;
nascent.reserve(minCapacity);
nascent.ml_.size_ = ml_.size_;
fbstring_detail::podCopy(
ml_.data_, ml_.data_ + ml_.size_ + 1, nascent.ml_.data_);
nascent.swap(*this);
(static_cast<bool>(capacity() >= minCapacity)
? void(0)
: __assert_fail(
"capacity() >= minCapacity",
"tlm/deps/folly.exploded/include/folly/FBString.h",
819,
__extension__ __PRETTY_FUNCTION__));
}
}
template <class Char>
__attribute__((__noinline__)) inline void fbstring_core<Char>::reserveSmall(
size_t minCapacity, const bool disableSSO) {
(static_cast<bool>(category() == Category::isSmall)
? void(0)
: __assert_fail("category() == Category::isSmall",
"tlm/deps/folly.exploded/include/folly/FBString.h",
827,
__extension__ __PRETTY_FUNCTION__));
if (!disableSSO && minCapacity <= maxSmallSize) {
} else if (minCapacity <= maxMediumSize) {
auto const allocSizeBytes =
goodMallocSize((1 + minCapacity) * sizeof(Char));
auto const pData = static_cast<Char*>(checkedMalloc(allocSizeBytes));
auto const size = smallSize();
fbstring_detail::podCopy(small_, small_ + size + 1, pData);
ml_.data_ = pData;
ml_.size_ = size;
ml_.setCapacity(allocSizeBytes / sizeof(Char) - 1, Category::isMedium);
} else {
auto const newRC = RefCounted::create(&minCapacity);
auto const size = smallSize();
fbstring_detail::podCopy(small_, small_ + size + 1, newRC->data_);
ml_.data_ = newRC->data_;
ml_.size_ = size;
ml_.setCapacity(minCapacity, Category::isLarge);
(static_cast<bool>(capacity() >= minCapacity)
? void(0)
: __assert_fail(
"capacity() >= minCapacity",
"tlm/deps/folly.exploded/include/folly/FBString.h",
852,
__extension__ __PRETTY_FUNCTION__));
}
}
template <class Char>
inline Char* fbstring_core<Char>::expandNoinit(const size_t delta,
bool expGrowth,
bool disableSSO) {
(static_cast<bool>(capacity() >= size())
? void(0)
: __assert_fail("capacity() >= size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
862,
__extension__ __PRETTY_FUNCTION__));
size_t sz, newSz;
if (category() == Category::isSmall) {
sz = smallSize();
newSz = sz + delta;
if (!disableSSO && (__builtin_expect((newSz <= maxSmallSize), 1))) {
setSmallSize(newSz);
return small_ + sz;
}
reserveSmall(expGrowth ? std::max(newSz, 2 * maxSmallSize) : newSz,
disableSSO);
} else {
sz = ml_.size_;
newSz = sz + delta;
if ((__builtin_expect((newSz > capacity()), 0))) {
reserve(expGrowth ? std::max(newSz, 1 + capacity() * 3 / 2)
: newSz);
}
}
(static_cast<bool>(capacity() >= newSz)
? void(0)
: __assert_fail("capacity() >= newSz",
"tlm/deps/folly.exploded/include/folly/FBString.h",
881,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(category() == Category::isMedium ||
category() == Category::isLarge)
? void(0)
: __assert_fail("category() == Category::isMedium || category() "
"== Category::isLarge",
"tlm/deps/folly.exploded/include/folly/FBString.h",
883,
__extension__ __PRETTY_FUNCTION__));
ml_.size_ = newSz;
ml_.data_[newSz] = '\0';
(static_cast<bool>(size() == newSz)
? void(0)
: __assert_fail("size() == newSz",
"tlm/deps/folly.exploded/include/folly/FBString.h",
886,
__extension__ __PRETTY_FUNCTION__));
return ml_.data_ + sz;
}
template <class Char>
inline void fbstring_core<Char>::shrinkSmall(const size_t delta) {
(static_cast<bool>(delta <= smallSize())
? void(0)
: __assert_fail("delta <= smallSize()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
893,
__extension__ __PRETTY_FUNCTION__));
setSmallSize(smallSize() - delta);
}
template <class Char>
inline void fbstring_core<Char>::shrinkMedium(const size_t delta) {
(static_cast<bool>(ml_.size_ >= delta)
? void(0)
: __assert_fail("ml_.size_ >= delta",
"tlm/deps/folly.exploded/include/folly/FBString.h",
901,
__extension__ __PRETTY_FUNCTION__));
ml_.size_ -= delta;
ml_.data_[ml_.size_] = '\0';
}
template <class Char>
inline void fbstring_core<Char>::shrinkLarge(const size_t delta) {
(static_cast<bool>(ml_.size_ >= delta)
? void(0)
: __assert_fail("ml_.size_ >= delta",
"tlm/deps/folly.exploded/include/folly/FBString.h",
908,
__extension__ __PRETTY_FUNCTION__));
if (delta) {
fbstring_core(ml_.data_, ml_.size_ - delta).swap(*this);
}
}
template <class Char>
class dummy_fbstring_core {
public:
dummy_fbstring_core() {
}
dummy_fbstring_core(const dummy_fbstring_core& another)
: backend_(another.backend_) {
}
dummy_fbstring_core(const Char* s, size_t n) : backend_(s, n) {
}
void swap(dummy_fbstring_core& rhs) {
backend_.swap(rhs.backend_);
}
const Char* data() const {
return backend_.data();
}
Char* mutableData() {
return const_cast<Char*>(backend_.data());
}
void shrink(size_t delta) {
(static_cast<bool>(delta <= size())
? void(0)
: __assert_fail(
"delta <= size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
939,
__extension__ __PRETTY_FUNCTION__));
backend_.resize(size() - delta);
}
Char* expandNoinit(size_t delta) {
auto const sz = size();
backend_.resize(size() + delta);
return backend_.data() + sz;
}
void push_back(Char c) {
backend_.push_back(c);
}
size_t size() const {
return backend_.size();
}
size_t capacity() const {
return backend_.capacity();
}
bool isShared() const {
return false;
}
void reserve(size_t minCapacity) {
backend_.reserve(minCapacity);
}
private:
std::basic_string<Char> backend_;
};
template <typename E,
class T = std::char_traits<E>,
class A = std::allocator<E>,
class Storage = fbstring_core<E>>
class basic_fbstring {
static_assert(std::is_same<A, std::allocator<E>>::value,
"fbstring ignores custom allocators");
template <typename Ex, typename... Args>
inline __attribute__((__always_inline__)) static void enforce(
bool condition, Args&&... args) {
if (!condition) {
throw_exception<Ex>(static_cast<Args&&>(args)...);
}
}
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 {
Invariant& operator=(const Invariant&) = delete;
explicit Invariant(const basic_fbstring& s) noexcept : s_(s) {
(static_cast<bool>(s_.isSane())
? void(0)
: __assert_fail("s_.isSane()",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
999,
__extension__ __PRETTY_FUNCTION__));
}
~Invariant() noexcept {
(static_cast<bool>(s_.isSane())
? void(0)
: __assert_fail("s_.isSane()",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
1002,
__extension__ __PRETTY_FUNCTION__));
}
private:
const basic_fbstring& s_;
};
public:
typedef T traits_type;
typedef typename traits_type::char_type value_type;
typedef A allocator_type;
typedef typename std::allocator_traits<A>::size_type size_type;
typedef typename std::allocator_traits<A>::difference_type difference_type;
typedef typename std::allocator_traits<A>::value_type& reference;
typedef typename std::allocator_traits<A>::value_type const&
const_reference;
typedef typename std::allocator_traits<A>::pointer pointer;
typedef typename std::allocator_traits<A>::const_pointer const_pointer;
typedef E* iterator;
typedef const E* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
static constexpr size_type npos = size_type(-1);
typedef std::true_type IsRelocatable;
private:
static void procrustes(size_type& n, size_type nmax) {
if (n > nmax) {
n = nmax;
}
}
static size_type traitsLength(const value_type* s);
public:
// # 1054 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
basic_fbstring() noexcept : basic_fbstring(A()) {
}
explicit basic_fbstring(const A&) noexcept {
}
basic_fbstring(const basic_fbstring& str) : store_(str.store_) {
}
basic_fbstring(basic_fbstring&& goner) noexcept
: store_(std::move(goner.store_)) {
}
template <typename A2>
basic_fbstring(const std::basic_string<E, T, A2>& str)
: store_(str.data(), str.size()) {
}
basic_fbstring(const basic_fbstring& str,
size_type pos,
size_type n = npos,
const A& = A()) {
assign(str, pos, n);
}
__attribute__((__noinline__))
basic_fbstring(const value_type* s, const A& = A())
: store_(s, traitsLength(s)) {
}
__attribute__((__noinline__))
basic_fbstring(const value_type* s, size_type n, const A& = A())
: store_(s, n) {
}
__attribute__((__noinline__))
basic_fbstring(size_type n, value_type c, const A& = A()) {
auto const pData = store_.expandNoinit(n);
fbstring_detail::podFill(pData, pData + n, c);
}
template <class InIt>
__attribute__((__noinline__)) basic_fbstring(
InIt begin,
InIt end,
typename std::enable_if<!std::is_same<InIt, value_type*>::value,
const A>::type& = A()) {
assign(begin, end);
}
__attribute__((__noinline__))
basic_fbstring(const value_type* b, const value_type* e, const A& = A())
: store_(b, size_type(e - b)) {
}
basic_fbstring(value_type* s,
size_type n,
size_type c,
AcquireMallocatedString a)
: store_(s, n, c, a) {
}
__attribute__((__noinline__))
basic_fbstring(std::initializer_list<value_type> il) {
assign(il.begin(), il.end());
}
~basic_fbstring() noexcept {
}
basic_fbstring& operator=(const basic_fbstring& lhs);
basic_fbstring& operator=(basic_fbstring&& goner) noexcept;
template <typename A2>
basic_fbstring& operator=(const std::basic_string<E, T, A2>& rhs) {
return assign(rhs.data(), rhs.size());
}
std::basic_string<E, T, A> toStdString() const {
return std::basic_string<E, T, A>(data(), size());
}
basic_fbstring& operator=(const value_type* s) {
return assign(s);
}
basic_fbstring& operator=(value_type c);
// # 1153 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
template <typename TP>
typename std::enable_if<
std::is_convertible<TP,
typename basic_fbstring<E, T, A, Storage>::
value_type>::value &&
!std::is_same<typename std::decay<TP>::type,
typename basic_fbstring<E, T, A, Storage>::
value_type>::value,
basic_fbstring<E, T, A, Storage>&>::type
operator=(TP c) = delete;
basic_fbstring& operator=(std::initializer_list<value_type> il) {
return assign(il.begin(), il.end());
}
operator std::basic_string_view<value_type, traits_type>() const noexcept {
return {data(), size()};
}
iterator begin() {
return store_.mutableData();
}
const_iterator begin() const {
return store_.data();
}
const_iterator cbegin() const {
return begin();
}
iterator end() {
return store_.mutableData() + 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();
}
const value_type& front() const {
return *begin();
}
const value_type& back() const {
(static_cast<bool>(!empty())
? void(0)
: __assert_fail(
"!empty()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1229,
__extension__ __PRETTY_FUNCTION__));
return *(end() - 1);
}
value_type& front() {
return *begin();
}
value_type& back() {
(static_cast<bool>(!empty())
? void(0)
: __assert_fail(
"!empty()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1237,
__extension__ __PRETTY_FUNCTION__));
return *(end() - 1);
}
void pop_back() {
(static_cast<bool>(!empty())
? void(0)
: __assert_fail(
"!empty()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1242,
__extension__ __PRETTY_FUNCTION__));
store_.shrink(1);
}
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(size_type n, value_type c = value_type());
size_type capacity() const {
return store_.capacity();
}
void reserve(size_type res_arg = 0) {
enforce<std::length_error>(res_arg <= max_size(), "");
store_.reserve(res_arg);
}
void shrink_to_fit() {
if (capacity() < size() * 3 / 2) {
return;
}
basic_fbstring(cbegin(), cend()).swap(*this);
}
void clear() {
resize(0);
}
bool empty() const {
return size() == 0;
}
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<std::out_of_range>(n < size(), "");
return (*this)[n];
}
reference at(size_type n) {
enforce<std::out_of_range>(n < size(), "");
return (*this)[n];
}
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);
basic_fbstring& append(const basic_fbstring& str,
const size_type pos,
size_type n);
basic_fbstring& append(const value_type* s, size_type n);
basic_fbstring& append(const value_type* s) {
return append(s, traitsLength(s));
}
basic_fbstring& append(size_type n, value_type c);
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) {
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);
basic_fbstring& assign(const value_type* s, const size_type n);
basic_fbstring& assign(const value_type* s) {
return assign(s, traitsLength(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<std::out_of_range>(pos2 <= str.length(), "");
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<std::out_of_range>(pos <= length(), "");
insert(begin() + pos, s, s + n);
return *this;
}
basic_fbstring& insert(size_type pos, const value_type* s) {
return insert(pos, s, traitsLength(s));
}
basic_fbstring& insert(size_type pos, size_type n, value_type c) {
enforce<std::out_of_range>(pos <= length(), "");
insert(begin() + pos, n, c);
return *this;
}
iterator insert(const_iterator p, const value_type c) {
const size_type pos = p - cbegin();
insert(p, 1, c);
return begin() + pos;
}
private:
typedef std::basic_istream<value_type, traits_type> istream_type;
istream_type& getlineImpl(istream_type& is, value_type delim);
public:
friend inline istream_type& getline(istream_type& is,
basic_fbstring& str,
value_type delim) {
return str.getlineImpl(is, delim);
}
friend inline istream_type& getline(istream_type& is, basic_fbstring& str) {
return getline(is, str, '\n');
}
private:
iterator insertImplDiscr(const_iterator i,
size_type n,
value_type c,
std::true_type);
template <class InputIter>
iterator insertImplDiscr(const_iterator i,
InputIter b,
InputIter e,
std::false_type);
template <class FwdIterator>
iterator insertImpl(const_iterator i,
FwdIterator s1,
FwdIterator s2,
std::forward_iterator_tag);
template <class InputIterator>
iterator insertImpl(const_iterator i,
InputIterator b,
InputIterator e,
std::input_iterator_tag);
public:
template <class ItOrLength, class ItOrChar>
iterator insert(const_iterator p,
ItOrLength first_or_n,
ItOrChar last_or_c) {
using Sel =
bool_constant<std::numeric_limits<ItOrLength>::is_specialized>;
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);
enforce<std::out_of_range>(pos <= length(), "");
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<std::out_of_range>(pos <= size(), "");
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;
}
basic_fbstring& replace(size_type pos1,
size_type n1,
const basic_fbstring& str) {
return replace(pos1, n1, str.data(), str.size());
}
basic_fbstring& replace(size_type pos1,
size_type n1,
const basic_fbstring& str,
size_type pos2,
size_type n2) {
enforce<std::out_of_range>(pos2 <= str.length(), "");
return replace(
pos1, n1, str.data() + pos2, std::min(n2, str.size() - pos2));
}
basic_fbstring& replace(size_type pos, size_type n1, const value_type* s) {
return replace(pos, n1, s, traitsLength(s));
}
// # 1518 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
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);
enforce<std::out_of_range>(pos <= size(), "");
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, traitsLength(s));
}
private:
basic_fbstring& replaceImplDiscr(iterator i1,
iterator i2,
const value_type* s,
size_type n,
std::integral_constant<int, 2>);
basic_fbstring& replaceImplDiscr(iterator i1,
iterator i2,
size_type n2,
value_type c,
std::integral_constant<int, 1>);
template <class InputIter>
basic_fbstring& replaceImplDiscr(iterator i1,
iterator i2,
InputIter b,
InputIter e,
std::integral_constant<int, 0>);
private:
template <class FwdIterator>
bool replaceAliased(
iterator, iterator, FwdIterator, FwdIterator, std::false_type) {
return false;
}
template <class FwdIterator>
bool replaceAliased(iterator i1,
iterator i2,
FwdIterator s1,
FwdIterator s2,
std::true_type);
template <class FwdIterator>
void replaceImpl(iterator i1,
iterator i2,
FwdIterator s1,
FwdIterator s2,
std::forward_iterator_tag);
template <class InputIterator>
void replaceImpl(iterator i1,
iterator i2,
InputIterator b,
InputIterator e,
std::input_iterator_tag);
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) {
constexpr bool num1 = std::numeric_limits<T1>::is_specialized,
num2 = std::numeric_limits<T2>::is_specialized;
using Sel =
std::integral_constant<int,
num1 ? (num2 ? 1 : -1) : (num2 ? 2 : 0)>;
return replaceImplDiscr(i1, i2, first_or_n_or_s, last_or_c_or_n, Sel());
}
size_type copy(value_type* s, size_type n, size_type pos = 0) const {
enforce<std::out_of_range>(pos <= size(), "");
procrustes(n, size() - pos);
if (n != 0) {
fbstring_detail::podCopy(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();
}
value_type* data() {
return store_.data();
}
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,
size_type pos,
size_type nsize) const;
size_type find(const value_type* s, size_type pos = 0) const {
return find(s, pos, traitsLength(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;
size_type rfind(const value_type* s, size_type pos = npos) const {
return rfind(s, pos, traitsLength(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;
size_type find_first_of(const value_type* s, size_type pos = 0) const {
return find_first_of(s, pos, traitsLength(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;
size_type find_last_of(const value_type* s, size_type pos = npos) const {
return find_last_of(s, pos, traitsLength(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;
size_type find_first_not_of(const value_type* s, size_type pos = 0) const {
return find_first_not_of(s, pos, traitsLength(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;
size_type find_last_not_of(const value_type* s,
size_type pos = npos) const {
return find_last_not_of(s, pos, traitsLength(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<std::out_of_range>(pos <= size(), "");
return basic_fbstring(data() + pos, std::min(n, size() - pos));
}
basic_fbstring substr(size_type pos = 0, size_type n = npos) && {
enforce<std::out_of_range>(pos <= size(), "");
erase(0, pos);
if (n < size()) {
resize(n);
}
return std::move(*this);
}
int compare(const basic_fbstring& str) const {
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, traitsLength(s));
}
int compare(size_type pos1,
size_type n1,
const value_type* s,
size_type n2) const {
enforce<std::out_of_range>(pos1 <= size(), "");
procrustes(n1, size() - pos1);
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<std::out_of_range>(pos2 <= str.size(), "");
return compare(
pos1, n1, str.data() + pos2, std::min(n2, str.size() - pos2));
}
int compare(const value_type* s) const {
const size_type n1(size()), n2(traitsLength(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:
Storage store_;
};
template <typename E, class T, class A, class S>
__attribute__((__noinline__)) inline
typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::traitsLength(const value_type* s) {
return s ? traits_type::length(s)
: (throw_exception<std::logic_error>(
"basic_fbstring: null pointer initializer not valid"),
0);
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=(
const basic_fbstring& lhs) {
Invariant checker(*this);
if ((__builtin_expect((&lhs == this), 0))) {
return *this;
}
return assign(lhs.data(), lhs.size());
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=(
basic_fbstring&& goner) noexcept {
if ((__builtin_expect((&goner == this), 0))) {
return *this;
}
this->~basic_fbstring();
new (&store_) S(std::move(goner.store_));
return *this;
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::operator=(
value_type c) {
Invariant checker(*this);
if (empty()) {
store_.expandNoinit(1);
} else if (store_.isShared()) {
basic_fbstring(1, c).swap(*this);
return *this;
} else {
store_.shrink(size() - 1);
}
front() = c;
return *this;
}
template <typename E, class T, class A, class S>
inline void basic_fbstring<E, T, A, S>::resize(const size_type n,
const value_type c) {
Invariant checker(*this);
auto size = this->size();
if (n <= size) {
store_.shrink(size - n);
} else {
auto const delta = n - size;
auto pData = store_.expandNoinit(delta);
fbstring_detail::podFill(pData, pData + delta, c);
}
(static_cast<bool>(this->size() == n)
? void(0)
: __assert_fail("this->size() == n",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1856,
__extension__ __PRETTY_FUNCTION__));
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
const basic_fbstring& str) {
auto desiredSize = size() + str.size();
append(str.data(), str.size());
(static_cast<bool>(size() == desiredSize)
? void(0)
: __assert_fail("size() == desiredSize",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1866,
__extension__ __PRETTY_FUNCTION__));
return *this;
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
const basic_fbstring& str, const size_type pos, size_type n) {
const size_type sz = str.size();
enforce<std::out_of_range>(pos <= sz, "");
procrustes(n, sz - pos);
return append(str.data() + pos, n);
}
template <typename E, class T, class A, class S>
__attribute__((__noinline__)) inline basic_fbstring<E, T, A, S>&
basic_fbstring<E, T, A, S>::append(const value_type* s, size_type n) {
Invariant checker(*this);
if ((__builtin_expect((!n), 0))) {
return *this;
}
auto const oldSize = size();
auto const oldData = data();
auto pData = store_.expandNoinit(n, true);
std::less_equal<const value_type*> le;
if ((__builtin_expect((le(oldData, s) && !le(oldData + oldSize, s)), 0))) {
(static_cast<bool>(le(s + n, oldData + oldSize))
? void(0)
: __assert_fail(
"le(s + n, oldData + oldSize)",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1902,
__extension__ __PRETTY_FUNCTION__));
s = data() + (s - oldData);
fbstring_detail::podMove(s, s + n, pData);
} else {
fbstring_detail::podCopy(s, s + n, pData);
}
(static_cast<bool>(size() == oldSize + n)
? void(0)
: __assert_fail("size() == oldSize + n",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1910,
__extension__ __PRETTY_FUNCTION__));
return *this;
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::append(
size_type n, value_type c) {
Invariant checker(*this);
auto pData = store_.expandNoinit(n, true);
fbstring_detail::podFill(pData, pData + n, c);
return *this;
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::assign(
const basic_fbstring& str, const size_type pos, size_type n) {
const size_type sz = str.size();
enforce<std::out_of_range>(pos <= sz, "");
procrustes(n, sz - pos);
return assign(str.data() + pos, n);
}
template <typename E, class T, class A, class S>
__attribute__((__noinline__)) inline basic_fbstring<E, T, A, S>&
basic_fbstring<E, T, A, S>::assign(const value_type* s, const size_type n) {
Invariant checker(*this);
if (n == 0) {
resize(0);
} else if (size() >= n) {
fbstring_detail::podMove(s, s + n, store_.mutableData());
store_.shrink(size() - n);
(static_cast<bool>(size() == n)
? void(0)
: __assert_fail(
"size() == n",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1946,
__extension__ __PRETTY_FUNCTION__));
} else {
resize(0);
fbstring_detail::podCopy(s, s + n, store_.expandNoinit(n));
}
(static_cast<bool>(size() == n)
? void(0)
: __assert_fail("size() == n",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1956,
__extension__ __PRETTY_FUNCTION__));
return *this;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::istream_type&
basic_fbstring<E, T, A, S>::getlineImpl(istream_type& is, value_type delim) {
Invariant checker(*this);
clear();
size_t size = 0;
while (true) {
size_t avail = capacity() - size;
is.getline(store_.expandNoinit(avail), avail + 1, delim);
size += is.gcount();
if (is.bad() || is.eof() || !is.fail()) {
if (!is.bad() && !is.eof()) {
--size;
}
resize(size);
break;
}
(static_cast<bool>(size == this->size())
? void(0)
: __assert_fail(
"size == this->size()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1983,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(size == capacity())
? void(0)
: __assert_fail(
"size == capacity()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
1984,
__extension__ __PRETTY_FUNCTION__));
reserve(std::max<size_t>(63, 3 * size / 2));
is.clear();
}
return is;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::find(const value_type* needle,
const size_type pos,
const size_type nsize) const {
auto const size = this->size();
if (nsize + pos > size || nsize + pos < pos) {
return npos;
}
if (nsize == 0) {
return pos;
}
auto const haystack = data();
auto const nsize_1 = nsize - 1;
auto const lastNeedle = needle[nsize_1];
size_type skip = 0;
const E* i = haystack + pos;
auto iEnd = haystack + size - nsize_1;
while (i < iEnd) {
while (i[nsize_1] != lastNeedle) {
if (++i == iEnd) {
return npos;
}
}
for (size_t j = 0;;) {
(static_cast<bool>(j < nsize)
? void(0)
: __assert_fail("j < nsize",
"tlm/deps/folly.exploded/include/folly/"
"FBString.h",
2034,
__extension__ __PRETTY_FUNCTION__));
if (i[j] != needle[j]) {
if (skip == 0) {
skip = 1;
while (skip <= nsize_1 &&
needle[nsize_1 - skip] != lastNeedle) {
++skip;
}
}
i += skip;
break;
}
if (++j == nsize) {
return i - haystack;
}
}
}
return npos;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::iterator
basic_fbstring<E, T, A, S>::insertImplDiscr(const_iterator i,
size_type n,
value_type c,
std::true_type) {
Invariant checker(*this);
(static_cast<bool>(i >= cbegin() && i <= cend())
? void(0)
: __assert_fail("i >= cbegin() && i <= cend()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2066,
__extension__ __PRETTY_FUNCTION__));
const size_type pos = i - cbegin();
auto oldSize = size();
store_.expandNoinit(n, true);
auto b = begin();
fbstring_detail::podMove(b + pos, b + oldSize, b + pos + n);
fbstring_detail::podFill(b + pos, b + pos + n, c);
return b + pos;
}
template <typename E, class T, class A, class S>
template <class InputIter>
inline typename basic_fbstring<E, T, A, S>::iterator
basic_fbstring<E, T, A, S>::insertImplDiscr(const_iterator i,
InputIter b,
InputIter e,
std::false_type) {
return insertImpl(
i,
b,
e,
typename std::iterator_traits<InputIter>::iterator_category());
}
template <typename E, class T, class A, class S>
template <class FwdIterator>
inline typename basic_fbstring<E, T, A, S>::iterator
basic_fbstring<E, T, A, S>::insertImpl(const_iterator i,
FwdIterator s1,
FwdIterator s2,
std::forward_iterator_tag) {
Invariant checker(*this);
(static_cast<bool>(i >= cbegin() && i <= cend())
? void(0)
: __assert_fail("i >= cbegin() && i <= cend()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2100,
__extension__ __PRETTY_FUNCTION__));
const size_type pos = i - cbegin();
auto n = std::distance(s1, s2);
(static_cast<bool>(n >= 0)
? void(0)
: __assert_fail("n >= 0",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2103,
__extension__ __PRETTY_FUNCTION__));
auto oldSize = size();
store_.expandNoinit(n, true);
auto b = begin();
fbstring_detail::podMove(b + pos, b + oldSize, b + pos + n);
std::copy(s1, s2, b + pos);
return b + pos;
}
template <typename E, class T, class A, class S>
template <class InputIterator>
inline typename basic_fbstring<E, T, A, S>::iterator
basic_fbstring<E, T, A, S>::insertImpl(const_iterator i,
InputIterator b,
InputIterator e,
std::input_iterator_tag) {
const auto pos = i - cbegin();
basic_fbstring temp(cbegin(), i);
for (; b != e; ++b) {
temp.push_back(*b);
}
temp.append(i, cend());
swap(temp);
return begin() + pos;
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
iterator i1,
iterator i2,
const value_type* s,
size_type n,
std::integral_constant<int, 2>) {
(static_cast<bool>(i1 <= i2)
? void(0)
: __assert_fail("i1 <= i2",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2139,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(begin() <= i1 && i1 <= end())
? void(0)
: __assert_fail("begin() <= i1 && i1 <= end()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2140,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(begin() <= i2 && i2 <= end())
? void(0)
: __assert_fail("begin() <= i2 && i2 <= end()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2141,
__extension__ __PRETTY_FUNCTION__));
return replace(i1, i2, s, s + n);
}
template <typename E, class T, class A, class S>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
iterator i1,
iterator i2,
size_type n2,
value_type c,
std::integral_constant<int, 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);
}
(static_cast<bool>(isSane())
? void(0)
: __assert_fail("isSane()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2160,
__extension__ __PRETTY_FUNCTION__));
return *this;
}
template <typename E, class T, class A, class S>
template <class InputIter>
inline basic_fbstring<E, T, A, S>& basic_fbstring<E, T, A, S>::replaceImplDiscr(
iterator i1,
iterator i2,
InputIter b,
InputIter e,
std::integral_constant<int, 0>) {
using Cat = typename std::iterator_traits<InputIter>::iterator_category;
replaceImpl(i1, i2, b, e, Cat());
return *this;
}
template <typename E, class T, class A, class S>
template <class FwdIterator>
inline bool basic_fbstring<E, T, A, S>::replaceAliased(iterator i1,
iterator i2,
FwdIterator s1,
FwdIterator s2,
std::true_type) {
std::less_equal<const value_type*> le{};
const bool aliased = le(&*begin(), &*s1) && le(&*s1, &*end());
if (!aliased) {
return false;
}
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 <typename E, class T, class A, class S>
template <class FwdIterator>
inline void basic_fbstring<E, T, A, S>::replaceImpl(iterator i1,
iterator i2,
FwdIterator s1,
FwdIterator s2,
std::forward_iterator_tag) {
Invariant checker(*this);
using Sel = bool_constant<std::is_same<FwdIterator, iterator>::value ||
std::is_same<FwdIterator, const_iterator>::value>;
if (replaceAliased(i1, i2, s1, s2, Sel())) {
return;
}
auto const n1 = i2 - i1;
(static_cast<bool>(n1 >= 0)
? void(0)
: __assert_fail("n1 >= 0",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2217,
__extension__ __PRETTY_FUNCTION__));
auto const n2 = std::distance(s1, s2);
(static_cast<bool>(n2 >= 0)
? void(0)
: __assert_fail("n2 >= 0",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2219,
__extension__ __PRETTY_FUNCTION__));
if (n1 > n2) {
std::copy(s1, s2, i1);
erase(i1 + n2, i2);
} else {
s1 = fbstring_detail::copy_n(s1, n1, i1).first;
insert(i2, s1, s2);
}
(static_cast<bool>(isSane())
? void(0)
: __assert_fail("isSane()",
"tlm/deps/folly.exploded/include/folly/FBString.h",
2230,
__extension__ __PRETTY_FUNCTION__));
}
template <typename E, class T, class A, class S>
template <class InputIterator>
inline void basic_fbstring<E, T, A, S>::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);
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::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;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::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) != nullptr) {
return i - begin();
}
}
return npos;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::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) != nullptr) {
return i - begin();
}
if (i == begin()) {
break;
}
}
}
return npos;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::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) == nullptr) {
return i - begin();
}
}
}
return npos;
}
template <typename E, class T, class A, class S>
inline typename basic_fbstring<E, T, A, S>::size_type
basic_fbstring<E, T, A, S>::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) == nullptr) {
return i - begin();
}
if (i == begin()) {
break;
}
}
}
return npos;
}
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 result;
}
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));
}
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()) {
return std::move(rhs.insert(0, lhs));
}
auto const& rhsC = rhs;
return lhs + rhsC;
}
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 E* lhs, const basic_fbstring<E, T, A, S>& rhs) {
basic_fbstring<E, T, A, S> result;
const auto 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+(const E* lhs,
basic_fbstring<E, T, A, S>&& rhs) {
const auto len = basic_fbstring<E, T, A, S>::traits_type::length(lhs);
if (rhs.capacity() >= len + rhs.size()) {
rhs.insert(rhs.begin(), lhs, lhs + len);
return std::move(rhs);
}
basic_fbstring<E, T, A, S> result;
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+(
E 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+(E lhs,
basic_fbstring<E, T, A, S>&& rhs) {
if (rhs.capacity() > rhs.size()) {
rhs.insert(rhs.begin(), lhs);
return std::move(rhs);
}
auto const& rhsC = rhs;
return lhs + rhsC;
}
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 E* 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+(basic_fbstring<E, T, A, S>&& lhs,
const E* rhs) {
return std::move(lhs += rhs);
}
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, E 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 basic_fbstring<E, T, A, S> operator+(basic_fbstring<E, T, A, S>&& lhs,
E rhs) {
return std::move(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.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);
}
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);
}
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) {
typedef std::basic_istream<typename basic_fbstring<E, T, A, S>::value_type,
typename basic_fbstring<E, T, A, S>::traits_type>
_istream_type;
typename _istream_type::sentry sentry(is);
size_t extracted = 0;
typename _istream_type::iostate err = _istream_type::goodbit;
if (sentry) {
auto n = is.width();
if (n <= 0) {
n = str.max_size();
}
str.erase();
for (auto got = is.rdbuf()->sgetc(); extracted != size_t(n);
++extracted) {
if (got == T::eof()) {
err |= _istream_type::eofbit;
is.width(0);
break;
}
if (isspace(got)) {
break;
}
str.push_back(got);
got = is.rdbuf()->snextc();
}
}
if (!extracted) {
err |= _istream_type::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) {
// # 2712 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
std::__ostream_insert(os, str.data(), str.size());
return os;
}
template <typename E1, class T, class A, class S>
constexpr typename basic_fbstring<E1, T, A, S>::size_type
basic_fbstring<E1, T, A, S>::npos;
template <typename E, class T, class A, class S, class A2>
inline bool operator==(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) == 0;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator==(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs == lhs;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator!=(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return !(lhs == rhs);
}
template <typename E, class T, class A, class S, class A2>
inline bool operator!=(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs == rhs);
}
template <typename E, class T, class A, class S, class A2>
inline bool operator<(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) < 0;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator>(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return lhs.compare(0, lhs.size(), rhs.data(), rhs.size()) > 0;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator<(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs > lhs;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator>(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return rhs < lhs;
}
template <typename E, class T, class A, class S, class A2>
inline bool operator<=(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return !(lhs > rhs);
}
template <typename E, class T, class A, class S, class A2>
inline bool operator>=(const basic_fbstring<E, T, A, S>& lhs,
const std::basic_string<E, T, A2>& rhs) {
return !(lhs < rhs);
}
template <typename E, class T, class A, class S, class A2>
inline bool operator<=(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs > rhs);
}
template <typename E, class T, class A, class S, class A2>
inline bool operator>=(const std::basic_string<E, T, A2>& lhs,
const basic_fbstring<E, T, A, S>& rhs) {
return !(lhs < rhs);
}
typedef basic_fbstring<char> fbstring;
template <class T, class R, class A, class S>
struct IsRelocatable<basic_fbstring<T, R, A, S>> : std::true_type {};
inline std::string toStdString(const folly::fbstring& s) {
return std::string(s.data(), s.size());
}
inline const std::string& toStdString(const std::string& s) {
return s;
}
inline std::string&& toStdString(std::string&& s) {
return std::move(s);
}
} // namespace folly
// # 2849 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
namespace std {
template <>
struct hash<::folly::basic_fbstring<char>> {
size_t operator()(const ::folly::basic_fbstring<char>& s) const {
return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(char));
}
};
template <>
struct hash<::folly::basic_fbstring<char16_t>> {
size_t operator()(const ::folly::basic_fbstring<char16_t>& s) const {
return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(char16_t));
}
};
template <>
struct hash<::folly::basic_fbstring<char32_t>> {
size_t operator()(const ::folly::basic_fbstring<char32_t>& s) const {
return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(char32_t));
}
};
template <>
struct hash<::folly::basic_fbstring<wchar_t>> {
size_t operator()(const ::folly::basic_fbstring<wchar_t>& s) const {
return ::folly::hash::fnv32_buf(s.data(), s.size() * sizeof(wchar_t));
}
};
} // namespace std
// # 2858 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
#pragma GCC diagnostic pop
// # 2858 "tlm/deps/folly.exploded/include/folly/FBString.h" 3 4
namespace folly {
template <class T>
struct IsSomeString;
template <>
struct IsSomeString<fbstring> : std::true_type {};
} // namespace folly
// # 20 "tlm/deps/folly.exploded/include/folly/Demangle.h" 2 3 4
namespace folly {
// # 34 "tlm/deps/folly.exploded/include/folly/Demangle.h" 3 4
fbstring demangle(const char* name);
inline fbstring demangle(const std::type_info& type) {
return demangle(type.name());
}
// # 57 "tlm/deps/folly.exploded/include/folly/Demangle.h" 3 4
size_t demangle(const char* name, char* out, size_t outSize);
inline size_t demangle(const std::type_info& type, char* buf, size_t bufSize) {
return demangle(type.name(), buf, bufSize);
}
} // namespace folly
// # 117 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Expected.h" 1 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
// # 35 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Optional.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/Optional.h" 3 4
// # 69 "tlm/deps/folly.exploded/include/folly/Optional.h" 3 4
namespace folly {
template <class Value>
class Optional;
namespace detail {
template <class Value>
struct OptionalPromiseReturn;
}
struct None {
enum class _secret { _token };
explicit constexpr None(_secret) {
}
};
constexpr None none{None::_secret::_token};
class __attribute__((__visibility__("default"))) OptionalEmptyException
: public std::runtime_error {
public:
OptionalEmptyException()
: std::runtime_error("Empty Optional cannot be unwrapped") {
}
};
template <class Value>
class Optional {
public:
typedef Value value_type;
static_assert(!std::is_reference<Value>::value,
"Optional may not be used with reference types");
static_assert(!std::is_abstract<Value>::value,
"Optional may not be used with abstract types");
constexpr Optional() noexcept {
}
Optional(const Optional& src) noexcept(
std::is_nothrow_copy_constructible<Value>::value) {
if (src.hasValue()) {
construct(src.value());
}
}
Optional(Optional&& src) noexcept(
std::is_nothrow_move_constructible<Value>::value) {
if (src.hasValue()) {
construct(std::move(src.value()));
src.reset();
}
}
constexpr Optional(const None&) noexcept {
}
constexpr Optional(Value&& newValue) noexcept(
std::is_nothrow_move_constructible<Value>::value) {
construct(std::move(newValue));
}
constexpr Optional(const Value& newValue) noexcept(
std::is_nothrow_copy_constructible<Value>::value) {
construct(newValue);
}
template <typename... Args>
constexpr explicit Optional(in_place_t, Args&&... args) noexcept(
std::is_nothrow_constructible<Value, Args...>::value)
: Optional{PrivateConstructor{}, std::forward<Args>(args)...} {
}
template <typename U, typename... Args>
constexpr explicit Optional(
in_place_t,
std::initializer_list<U> il,
Args&&... args) noexcept(std::
is_nothrow_constructible<
Value,
std::initializer_list<U>,
Args...>::value)
: Optional{PrivateConstructor{}, il, std::forward<Args>(args)...} {
}
Optional(const detail::OptionalPromiseReturn<Value>& p) : Optional{} {
p.promise_->value_ = this;
}
void assign(const None&) {
reset();
}
void assign(Optional&& src) {
if (this != &src) {
if (src.hasValue()) {
assign(std::move(src.value()));
src.reset();
} else {
reset();
}
}
}
void assign(const Optional& src) {
if (src.hasValue()) {
assign(src.value());
} else {
reset();
}
}
void assign(Value&& newValue) {
if (hasValue()) {
storage_.value = std::move(newValue);
} else {
construct(std::move(newValue));
}
}
void assign(const Value& newValue) {
if (hasValue()) {
storage_.value = newValue;
} else {
construct(newValue);
}
}
Optional& operator=(None) noexcept {
reset();
return *this;
}
template <class Arg>
Optional& operator=(Arg&& arg) {
assign(std::forward<Arg>(arg));
return *this;
}
Optional& operator=(Optional&& other) noexcept(
std::is_nothrow_move_assignable<Value>::value) {
assign(std::move(other));
return *this;
}
Optional& operator=(const Optional& other) noexcept(
std::is_nothrow_copy_assignable<Value>::value) {
assign(other);
return *this;
}
template <class... Args>
Value& emplace(Args&&... args) {
reset();
construct(std::forward<Args>(args)...);
return value();
}
template <class U, class... Args>
typename std::enable_if<std::is_constructible<Value,
std::initializer_list<U>&,
Args&&...>::value,
Value&>::type
emplace(std::initializer_list<U> ilist, Args&&... args) {
reset();
construct(ilist, std::forward<Args>(args)...);
return value();
}
void reset() noexcept {
storage_.clear();
}
void clear() noexcept {
reset();
}
void swap(Optional& that) noexcept(IsNothrowSwappable<Value>::value) {
if (hasValue() && that.hasValue()) {
using std::swap;
swap(value(), that.value());
} else if (hasValue()) {
that.emplace(std::move(value()));
reset();
} else if (that.hasValue()) {
emplace(std::move(that.value()));
that.reset();
}
}
constexpr const Value& value() const& {
require_value();
return storage_.value;
}
constexpr Value& value() & {
require_value();
return storage_.value;
}
constexpr Value&& value() && {
require_value();
return std::move(storage_.value);
}
constexpr const Value&& value() const&& {
require_value();
return std::move(storage_.value);
}
const Value* get_pointer() const& {
return storage_.hasValue ? &storage_.value : nullptr;
}
Value* get_pointer() & {
return storage_.hasValue ? &storage_.value : nullptr;
}
Value* get_pointer() && = delete;
constexpr bool has_value() const noexcept {
return storage_.hasValue;
}
constexpr bool hasValue() const noexcept {
return has_value();
}
constexpr explicit operator bool() const noexcept {
return has_value();
}
constexpr const Value& operator*() const& {
return value();
}
constexpr Value& operator*() & {
return value();
}
constexpr const Value&& operator*() const&& {
return std::move(value());
}
constexpr Value&& operator*() && {
return std::move(value());
}
constexpr const Value* operator->() const {
return &value();
}
constexpr Value* operator->() {
return &value();
}
template <class U>
constexpr Value value_or(U&& dflt) const& {
if (storage_.hasValue) {
return storage_.value;
}
return std::forward<U>(dflt);
}
template <class U>
constexpr Value value_or(U&& dflt) && {
if (storage_.hasValue) {
return std::move(storage_.value);
}
return std::forward<U>(dflt);
}
private:
template <class T>
friend constexpr Optional<std::decay_t<T>> make_optional(T&&);
template <class T, class... Args>
friend constexpr Optional<T> make_optional(Args&&... args);
template <class T, class U, class... As>
friend constexpr Optional<T> make_optional(std::initializer_list<U>,
As&&...);
// # 354 "tlm/deps/folly.exploded/include/folly/Optional.h" 3 4
struct PrivateConstructor {
explicit PrivateConstructor() = default;
};
template <typename... Args>
constexpr Optional(PrivateConstructor, Args&&... args) noexcept(
std::is_constructible<Value, Args&&...>::value) {
construct(std::forward<Args>(args)...);
}
void require_value() const {
if (!storage_.hasValue) {
throw_exception<OptionalEmptyException>();
}
}
template <class... Args>
void construct(Args&&... args) {
const void* ptr = &storage_.value;
new (const_cast<void*>(ptr)) Value(std::forward<Args>(args)...);
storage_.hasValue = true;
}
struct StorageTriviallyDestructible {
union {
char emptyState;
Value value;
};
bool hasValue;
constexpr StorageTriviallyDestructible()
: emptyState('\0'), hasValue{false} {
}
void clear() {
hasValue = false;
}
};
struct StorageNonTriviallyDestructible {
union {
char emptyState;
Value value;
};
bool hasValue;
StorageNonTriviallyDestructible() : hasValue{false} {
}
~StorageNonTriviallyDestructible() {
clear();
}
void clear() {
if (hasValue) {
hasValue = false;
value.~Value();
}
}
};
using Storage = typename std::conditional<
std::is_trivially_destructible<Value>::value,
StorageTriviallyDestructible,
StorageNonTriviallyDestructible>::type;
Storage storage_;
};
template <class T>
const T* get_pointer(const Optional<T>& opt) {
return opt.get_pointer();
}
template <class T>
T* get_pointer(Optional<T>& opt) {
return opt.get_pointer();
}
template <class T>
void swap(Optional<T>& a, Optional<T>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
template <class T>
constexpr Optional<std::decay_t<T>> make_optional(T&& v) {
using PrivateConstructor =
typename folly::Optional<std::decay_t<T>>::PrivateConstructor;
return {PrivateConstructor{}, std::forward<T>(v)};
}
template <class T, class... Args>
constexpr folly::Optional<T> make_optional(Args&&... args) {
using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor;
return {PrivateConstructor{}, std::forward<Args>(args)...};
}
template <class T, class U, class... Args>
constexpr folly::Optional<T> make_optional(std::initializer_list<U> il,
Args&&... args) {
using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor;
return {PrivateConstructor{}, il, std::forward<Args>(args)...};
}
template <class U, class V>
constexpr bool operator==(const Optional<U>& a, const V& b) {
return a.hasValue() && a.value() == b;
}
template <class U, class V>
constexpr bool operator!=(const Optional<U>& a, const V& b) {
return !(a == b);
}
template <class U, class V>
constexpr bool operator==(const U& a, const Optional<V>& b) {
return b.hasValue() && b.value() == a;
}
template <class U, class V>
constexpr bool operator!=(const U& a, const Optional<V>& b) {
return !(a == b);
}
template <class U, class V>
constexpr bool operator==(const Optional<U>& a, const Optional<V>& b) {
if (a.hasValue() != b.hasValue()) {
return false;
}
if (a.hasValue()) {
return a.value() == b.value();
}
return true;
}
template <class U, class V>
constexpr bool operator!=(const Optional<U>& a, const Optional<V>& b) {
return !(a == b);
}
template <class U, class V>
constexpr bool operator<(const Optional<U>& a, const Optional<V>& b) {
if (a.hasValue() != b.hasValue()) {
return a.hasValue() < b.hasValue();
}
if (a.hasValue()) {
return a.value() < b.value();
}
return false;
}
template <class U, class V>
constexpr bool operator>(const Optional<U>& a, const Optional<V>& b) {
return b < a;
}
template <class U, class V>
constexpr bool operator<=(const Optional<U>& a, const Optional<V>& b) {
return !(b < a);
}
template <class U, class V>
constexpr bool operator>=(const Optional<U>& a, const Optional<V>& b) {
return !(a < b);
}
template <class V>
bool operator<(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator<=(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator>=(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator>(const Optional<V>&, const V& other) = delete;
template <class V>
bool operator<(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator<=(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator>=(const V& other, const Optional<V>&) = delete;
template <class V>
bool operator>(const V& other, const Optional<V>&) = delete;
template <class V>
constexpr bool operator==(const Optional<V>& a, None) noexcept {
return !a.hasValue();
}
template <class V>
constexpr bool operator==(None, const Optional<V>& a) noexcept {
return !a.hasValue();
}
template <class V>
constexpr bool operator<(const Optional<V>&, None) noexcept {
return false;
}
template <class V>
constexpr bool operator<(None, const Optional<V>& a) noexcept {
return a.hasValue();
}
template <class V>
constexpr bool operator>(const Optional<V>& a, None) noexcept {
return a.hasValue();
}
template <class V>
constexpr bool operator>(None, const Optional<V>&) noexcept {
return false;
}
template <class V>
constexpr bool operator<=(None, const Optional<V>&) noexcept {
return true;
}
template <class V>
constexpr bool operator<=(const Optional<V>& a, None) noexcept {
return !a.hasValue();
}
template <class V>
constexpr bool operator>=(const Optional<V>&, None) noexcept {
return true;
}
template <class V>
constexpr bool operator>=(None, const Optional<V>& a) noexcept {
return !a.hasValue();
}
} // namespace folly
namespace std {
template <class T>
struct hash<folly::Optional<T>> {
size_t operator()(folly::Optional<T> const& obj) const {
if (!obj.hasValue()) {
return 0;
}
return hash<typename remove_const<T>::type>()(*obj);
}
};
} // namespace std
// # 36 "tlm/deps/folly.exploded/include/folly/Expected.h" 2 3 4
// # 55 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
namespace folly {
template <class Error>
class Unexpected;
template <class Error>
constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(Error&&);
template <class Value, class Error>
class Expected;
template <class Error, class Value>
constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
Value&&);
template <class Expected>
using ExpectedValueType =
typename std::remove_reference<Expected>::type::value_type;
template <class Expected>
using ExpectedErrorType =
typename std::remove_reference<Expected>::type::error_type;
namespace expected_detail {
template <typename Value, typename Error>
struct PromiseReturn;
template <template <class...> class Trait, class... Ts>
using StrictAllOf = StrictConjunction<Trait<Ts>...>;
template <class T>
using IsCopyable = StrictConjunction<std::is_copy_constructible<T>,
std::is_copy_assignable<T>>;
template <class T>
using IsMovable = StrictConjunction<std::is_move_constructible<T>,
std::is_move_assignable<T>>;
template <class T>
using IsNothrowCopyable =
StrictConjunction<std::is_nothrow_copy_constructible<T>,
std::is_nothrow_copy_assignable<T>>;
template <class T>
using IsNothrowMovable =
StrictConjunction<std::is_nothrow_move_constructible<T>,
std::is_nothrow_move_assignable<T>>;
template <class From, class To>
using IsConvertible = StrictConjunction<std::is_constructible<To, From>,
std::is_assignable<To&, From>>;
template <class T, class U>
auto doEmplaceAssign(int, T& t, U&& u)
-> decltype(void(t = static_cast<U&&>(u))) {
t = static_cast<U&&>(u);
}
template <class T, class U>
auto doEmplaceAssign(long, T& t, U&& u)
-> decltype(void(T(static_cast<U&&>(u)))) {
t.~T();
::new ((void*)std::addressof(t)) T(static_cast<U&&>(u));
}
template <class T, class... Us>
auto doEmplaceAssign(int, T& t, Us&&... us)
-> decltype(void(t = T(static_cast<Us&&>(us)...))) {
t = T(static_cast<Us&&>(us)...);
}
template <class T, class... Us>
auto doEmplaceAssign(long, T& t, Us&&... us)
-> decltype(void(T(static_cast<Us&&>(us)...))) {
t.~T();
::new ((void*)std::addressof(t)) T(static_cast<Us&&>(us)...);
}
struct EmptyTag {};
struct ValueTag {};
struct ErrorTag {};
enum class Which : unsigned char { eEmpty, eValue, eError };
enum class StorageType { ePODStruct, ePODUnion, eUnion };
template <class Value, class Error>
constexpr StorageType getStorageType() {
return StrictAllOf<is_trivially_copyable, Value, Error>::value
? (sizeof(std::pair<Value, Error>) <= sizeof(void* [2]) &&
StrictAllOf<std::is_trivial,
Value,
Error>::value
? StorageType::ePODStruct
: StorageType::ePODUnion)
: StorageType::eUnion;
}
template <class Value,
class Error,
StorageType = expected_detail::getStorageType<Value, Error>()>
struct ExpectedStorage {
using value_type = Value;
using error_type = Error;
union {
Value value_;
Error error_;
char ch_;
};
Which which_;
template <class E = Error, class = decltype(E{})>
constexpr ExpectedStorage() noexcept(noexcept(E{}))
: error_{}, which_(Which::eError) {
}
explicit constexpr ExpectedStorage(EmptyTag) noexcept
: ch_{}, which_(Which::eEmpty) {
}
template <class... Vs>
explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
noexcept(Value(static_cast<Vs&&>(vs)...)))
: value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {
}
template <class... Es>
explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
noexcept(Error(static_cast<Es&&>(es)...)))
: error_(static_cast<Es&&>(es)...), which_(Which::eError) {
}
void clear() noexcept {
}
static constexpr bool uninitializedByException() noexcept {
return false;
}
template <class... Vs>
void assignValue(Vs&&... vs) {
expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
which_ = Which::eValue;
}
template <class... Es>
void assignError(Es&&... es) {
expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
which_ = Which::eError;
}
template <class Other>
void assign(Other&& that) {
switch (that.which_) {
case Which::eValue:
this->assignValue(static_cast<Other&&>(that).value());
break;
case Which::eError:
this->assignError(static_cast<Other&&>(that).error());
break;
case Which::eEmpty:
default:
this->clear();
break;
}
}
Value& value() & {
return value_;
}
const Value& value() const& {
return value_;
}
Value&& value() && {
return std::move(value_);
}
Error& error() & {
return error_;
}
const Error& error() const& {
return error_;
}
Error&& error() && {
return std::move(error_);
}
};
template <class Value, class Error>
struct ExpectedUnion {
union {
Value value_;
Error error_;
char ch_{};
};
Which which_ = Which::eEmpty;
explicit constexpr ExpectedUnion(EmptyTag) noexcept {
}
template <class... Vs>
explicit constexpr ExpectedUnion(ValueTag, Vs&&... vs) noexcept(
noexcept(Value(static_cast<Vs&&>(vs)...)))
: value_(static_cast<Vs&&>(vs)...), which_(Which::eValue) {
}
template <class... Es>
explicit constexpr ExpectedUnion(ErrorTag, Es&&... es) noexcept(
noexcept(Error(static_cast<Es&&>(es)...)))
: error_(static_cast<Es&&>(es)...), which_(Which::eError) {
}
ExpectedUnion(const ExpectedUnion&) {
}
ExpectedUnion(ExpectedUnion&&) noexcept {
}
ExpectedUnion& operator=(const ExpectedUnion&) {
return *this;
}
ExpectedUnion& operator=(ExpectedUnion&&) noexcept {
return *this;
}
~ExpectedUnion() {
}
Value& value() & {
return value_;
}
const Value& value() const& {
return value_;
}
Value&& value() && {
return std::move(value_);
}
Error& error() & {
return error_;
}
const Error& error() const& {
return error_;
}
Error&& error() && {
return std::move(error_);
}
};
template <class Derived, bool, bool Noexcept>
struct CopyConstructible {
constexpr CopyConstructible() = default;
CopyConstructible(const CopyConstructible& that) noexcept(Noexcept) {
static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
}
constexpr CopyConstructible(CopyConstructible&&) = default;
CopyConstructible& operator=(const CopyConstructible&) = default;
CopyConstructible& operator=(CopyConstructible&&) = default;
};
template <class Derived, bool Noexcept>
struct CopyConstructible<Derived, false, Noexcept> {
constexpr CopyConstructible() = default;
CopyConstructible(const CopyConstructible&) = delete;
constexpr CopyConstructible(CopyConstructible&&) = default;
CopyConstructible& operator=(const CopyConstructible&) = default;
CopyConstructible& operator=(CopyConstructible&&) = default;
};
template <class Derived, bool, bool Noexcept>
struct MoveConstructible {
constexpr MoveConstructible() = default;
constexpr MoveConstructible(const MoveConstructible&) = default;
MoveConstructible(MoveConstructible&& that) noexcept(Noexcept) {
static_cast<Derived*>(this)->assign(
std::move(static_cast<Derived&>(that)));
}
MoveConstructible& operator=(const MoveConstructible&) = default;
MoveConstructible& operator=(MoveConstructible&&) = default;
};
template <class Derived, bool Noexcept>
struct MoveConstructible<Derived, false, Noexcept> {
constexpr MoveConstructible() = default;
constexpr MoveConstructible(const MoveConstructible&) = default;
MoveConstructible(MoveConstructible&&) = delete;
MoveConstructible& operator=(const MoveConstructible&) = default;
MoveConstructible& operator=(MoveConstructible&&) = default;
};
template <class Derived, bool, bool Noexcept>
struct CopyAssignable {
constexpr CopyAssignable() = default;
constexpr CopyAssignable(const CopyAssignable&) = default;
constexpr CopyAssignable(CopyAssignable&&) = default;
CopyAssignable& operator=(const CopyAssignable& that) noexcept(Noexcept) {
static_cast<Derived*>(this)->assign(static_cast<const Derived&>(that));
return *this;
}
CopyAssignable& operator=(CopyAssignable&&) = default;
};
template <class Derived, bool Noexcept>
struct CopyAssignable<Derived, false, Noexcept> {
constexpr CopyAssignable() = default;
constexpr CopyAssignable(const CopyAssignable&) = default;
constexpr CopyAssignable(CopyAssignable&&) = default;
CopyAssignable& operator=(const CopyAssignable&) = delete;
CopyAssignable& operator=(CopyAssignable&&) = default;
};
template <class Derived, bool, bool Noexcept>
struct MoveAssignable {
constexpr MoveAssignable() = default;
constexpr MoveAssignable(const MoveAssignable&) = default;
constexpr MoveAssignable(MoveAssignable&&) = default;
MoveAssignable& operator=(const MoveAssignable&) = default;
MoveAssignable& operator=(MoveAssignable&& that) noexcept(Noexcept) {
static_cast<Derived*>(this)->assign(
std::move(static_cast<Derived&>(that)));
return *this;
}
};
template <class Derived, bool Noexcept>
struct MoveAssignable<Derived, false, Noexcept> {
constexpr MoveAssignable() = default;
constexpr MoveAssignable(const MoveAssignable&) = default;
constexpr MoveAssignable(MoveAssignable&&) = default;
MoveAssignable& operator=(const MoveAssignable&) = default;
MoveAssignable& operator=(MoveAssignable&& that) = delete;
};
template <class Value, class Error>
struct ExpectedStorage<Value, Error, StorageType::eUnion>
: ExpectedUnion<Value, Error>,
CopyConstructible<
ExpectedStorage<Value, Error, StorageType::eUnion>,
StrictAllOf<std::is_copy_constructible, Value, Error>::value,
StrictAllOf<std::is_nothrow_copy_constructible, Value, Error>::
value>,
MoveConstructible<
ExpectedStorage<Value, Error, StorageType::eUnion>,
StrictAllOf<std::is_move_constructible, Value, Error>::value,
StrictAllOf<std::is_nothrow_move_constructible, Value, Error>::
value>,
CopyAssignable<ExpectedStorage<Value, Error, StorageType::eUnion>,
StrictAllOf<IsCopyable, Value, Error>::value,
StrictAllOf<IsNothrowCopyable, Value, Error>::value>,
MoveAssignable<ExpectedStorage<Value, Error, StorageType::eUnion>,
StrictAllOf<IsMovable, Value, Error>::value,
StrictAllOf<IsNothrowMovable, Value, Error>::value> {
using value_type = Value;
using error_type = Error;
using Base = ExpectedUnion<Value, Error>;
template <class E = Error, class = decltype(E{})>
constexpr ExpectedStorage() noexcept(noexcept(E{})) : Base{ErrorTag{}} {
}
ExpectedStorage(const ExpectedStorage&) = default;
ExpectedStorage(ExpectedStorage&&) = default;
ExpectedStorage& operator=(const ExpectedStorage&) = default;
ExpectedStorage& operator=(ExpectedStorage&&) = default;
using ExpectedUnion<Value, Error>::ExpectedUnion;
~ExpectedStorage() {
clear();
}
void clear() noexcept {
switch (this->which_) {
case Which::eValue:
this->value().~Value();
break;
case Which::eError:
this->error().~Error();
break;
case Which::eEmpty:
default:
break;
}
this->which_ = Which::eEmpty;
}
bool uninitializedByException() const noexcept {
return this->which_ == Which::eEmpty;
}
template <class... Vs>
void assignValue(Vs&&... vs) {
if (this->which_ == Which::eValue) {
expected_detail::doEmplaceAssign(
0, this->value(), static_cast<Vs&&>(vs)...);
} else {
this->clear();
::new ((void*)std::addressof(this->value()))
Value(static_cast<Vs&&>(vs)...);
this->which_ = Which::eValue;
}
}
template <class... Es>
void assignError(Es&&... es) {
if (this->which_ == Which::eError) {
expected_detail::doEmplaceAssign(
0, this->error(), static_cast<Es&&>(es)...);
} else {
this->clear();
::new ((void*)std::addressof(this->error()))
Error(static_cast<Es&&>(es)...);
this->which_ = Which::eError;
}
}
bool isSelfAssign(const ExpectedStorage* that) const {
return this == that;
}
constexpr bool isSelfAssign(const void*) const {
return false;
}
template <class Other>
void assign(Other&& that) {
if (isSelfAssign(&that)) {
return;
}
switch (that.which_) {
case Which::eValue:
this->assignValue(static_cast<Other&&>(that).value());
break;
case Which::eError:
this->assignError(static_cast<Other&&>(that).error());
break;
case Which::eEmpty:
default:
this->clear();
break;
}
}
};
template <class Value, class Error>
struct ExpectedStorage<Value, Error, StorageType::ePODStruct> {
using value_type = Value;
using error_type = Error;
Which which_;
Error error_;
Value value_;
constexpr ExpectedStorage() noexcept
: which_(Which::eError), error_{}, value_{} {
}
explicit constexpr ExpectedStorage(EmptyTag) noexcept
: which_(Which::eEmpty), error_{}, value_{} {
}
template <class... Vs>
explicit constexpr ExpectedStorage(ValueTag, Vs&&... vs) noexcept(
noexcept(Value(static_cast<Vs&&>(vs)...)))
: which_(Which::eValue), error_{}, value_(static_cast<Vs&&>(vs)...) {
}
template <class... Es>
explicit constexpr ExpectedStorage(ErrorTag, Es&&... es) noexcept(
noexcept(Error(static_cast<Es&&>(es)...)))
: which_(Which::eError), error_(static_cast<Es&&>(es)...), value_{} {
}
void clear() noexcept {
}
constexpr static bool uninitializedByException() noexcept {
return false;
}
template <class... Vs>
void assignValue(Vs&&... vs) {
expected_detail::doEmplaceAssign(0, value_, static_cast<Vs&&>(vs)...);
which_ = Which::eValue;
}
template <class... Es>
void assignError(Es&&... es) {
expected_detail::doEmplaceAssign(0, error_, static_cast<Es&&>(es)...);
which_ = Which::eError;
}
template <class Other>
void assign(Other&& that) {
switch (that.which_) {
case Which::eValue:
this->assignValue(static_cast<Other&&>(that).value());
break;
case Which::eError:
this->assignError(static_cast<Other&&>(that).error());
break;
case Which::eEmpty:
default:
this->clear();
break;
}
}
Value& value() & {
return value_;
}
const Value& value() const& {
return value_;
}
Value&& value() && {
return std::move(value_);
}
Error& error() & {
return error_;
}
const Error& error() const& {
return error_;
}
Error&& error() && {
return std::move(error_);
}
};
namespace expected_detail_ExpectedHelper {
template <class T>
inline T&& operator,(T&& t, Unit) noexcept {
return static_cast<T&&>(t);
}
struct ExpectedHelper {
template <class Error, class T>
static constexpr Expected<T, Error> return_(T t) {
return folly::makeExpected<Error>(t);
}
template <class Error,
class T,
class U,
bool FollyRequires554 = false,
typename std::enable_if<
(FollyRequires554 ||
static_cast<bool>(
expected_detail::IsConvertible<U&&,
Error>::value)),
int>::type = 0>
static constexpr Expected<T, Error> return_(Expected<T, U> t) {
return t;
}
template <class This>
static typename std::decay<This>::type then_(This&& ex) {
return static_cast<This&&>(ex);
}
// # 565 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
#pragma GCC diagnostic push
// # 565 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
template <class This,
class Fn,
class... Fns,
class E = ExpectedErrorType<This>,
class T = ExpectedHelper>
static auto then_(This&& ex, Fn&& fn, Fns&&... fns) -> decltype(T::then_(
T::template return_<E>(
(std::declval<Fn>()(std::declval<This>().value()), unit)),
std::declval<Fns>()...)) {
if ((__builtin_expect((ex.which_ == expected_detail::Which::eValue),
1))) {
return T::then_(T::template return_<E>(
(static_cast<Fn&&>(fn)(
static_cast<This&&>(ex).value()),
unit)),
static_cast<Fns&&>(fns)...);
}
return makeUnexpected(static_cast<This&&>(ex).error());
}
template <class This,
class Yes,
class No,
class Ret = decltype(
std::declval<Yes>()(std::declval<This>().value())),
class Err = decltype(
std::declval<No>()(std::declval<This>().error())),
bool FollyRequires595 = false,
typename std::enable_if<
(FollyRequires595 ||
static_cast<bool>(!std::is_void<Err>::value)),
int>::type = 0>
static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
if ((__builtin_expect((ex.which_ == expected_detail::Which::eValue),
1))) {
return Ret(
static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
}
throw_exception(static_cast<No&&>(no)(static_cast<This&&>(ex).error()));
}
template <class This,
class Yes,
class No,
class Ret = decltype(
std::declval<Yes>()(std::declval<This>().value())),
class Err = decltype(
std::declval<No>()(std::declval<This&>().error())),
bool FollyRequires609 = false,
typename std::enable_if<
(FollyRequires609 ||
static_cast<bool>(std::is_void<Err>::value)),
int>::type = 0>
static Ret thenOrThrow_(This&& ex, Yes&& yes, No&& no) {
if ((__builtin_expect((ex.which_ == expected_detail::Which::eValue),
1))) {
return Ret(
static_cast<Yes&&>(yes)(static_cast<This&&>(ex).value()));
}
static_cast<No&&>(no)(ex.error());
typename Unexpected<ExpectedErrorType<This>>::MakeBadExpectedAccess bad;
throw_exception(bad(static_cast<This&&>(ex).error()));
}
// # 618 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
#pragma GCC diagnostic pop
// # 618 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
};
} // namespace expected_detail_ExpectedHelper
using expected_detail_ExpectedHelper::ExpectedHelper;
struct UnexpectedTag {};
} // namespace expected_detail
using unexpected_t =
expected_detail::UnexpectedTag (&)(expected_detail::UnexpectedTag);
inline expected_detail::UnexpectedTag unexpected(
expected_detail::UnexpectedTag = {}) {
return {};
}
class __attribute__((__visibility__("default"))) BadExpectedAccess
: public std::logic_error {
public:
BadExpectedAccess() : std::logic_error("bad Expected access") {
}
};
namespace expected_detail {}
template <class Error>
class Unexpected final {
template <class E>
friend class Unexpected;
template <class V, class E>
friend class Expected;
friend struct expected_detail::ExpectedHelper;
public:
class __attribute__((__visibility__("default"))) BadExpectedAccess
: public folly::BadExpectedAccess {
public:
explicit BadExpectedAccess(Error err)
: folly::BadExpectedAccess{}, error_(std::move(err)) {
}
Error error() const {
return error_;
}
private:
Error error_;
};
Unexpected() = default;
Unexpected(const Unexpected&) = default;
Unexpected(Unexpected&&) = default;
Unexpected& operator=(const Unexpected&) = default;
Unexpected& operator=(Unexpected&&) = default;
__attribute__((__cold__)) constexpr Unexpected(const Error& err)
: error_(err) {
}
__attribute__((__cold__)) constexpr Unexpected(Error&& err)
: error_(std::move(err)) {
}
template <class Other,
bool FollyRequires694 = false,
typename std::enable_if<
(FollyRequires694 ||
static_cast<bool>(
std::is_constructible<Error, Other&&>::value)),
int>::type = 0>
constexpr Unexpected(Unexpected<Other> that)
: error_(std::move(that.error())) {
}
template <class Other,
bool FollyRequires702 = false,
typename std::enable_if<
(FollyRequires702 ||
static_cast<bool>(
std::is_assignable<Error&, Other&&>::value)),
int>::type = 0>
Unexpected& operator=(Unexpected<Other> that) {
error_ = std::move(that.error());
}
Error& error() & {
return error_;
}
const Error& error() const& {
return error_;
}
Error&& error() && {
return std::move(error_);
}
private:
struct MakeBadExpectedAccess {
template <class E>
BadExpectedAccess operator()(E&& err) const {
return BadExpectedAccess(static_cast<E&&>(err));
}
};
Error error_;
};
template <class Error,
bool FollyRequires733 = false,
typename std::enable_if<
(FollyRequires733 ||
static_cast<bool>(IsEqualityComparable<Error>::value)),
int>::type = 0>
inline bool operator==(const Unexpected<Error>& lhs,
const Unexpected<Error>& rhs) {
return lhs.error() == rhs.error();
}
template <class Error,
bool FollyRequires741 = false,
typename std::enable_if<
(FollyRequires741 ||
static_cast<bool>(IsEqualityComparable<Error>::value)),
int>::type = 0>
inline bool operator!=(const Unexpected<Error>& lhs,
const Unexpected<Error>& rhs) {
return !(lhs == rhs);
}
// # 760 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
template <class Error>
constexpr Unexpected<typename std::decay<Error>::type> makeUnexpected(
Error&& err) {
return Unexpected<typename std::decay<Error>::type>{
static_cast<Error&&>(err)};
}
// # 861 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
template <class Value, class Error>
class Expected final : expected_detail::ExpectedStorage<Value, Error> {
template <class, class>
friend class Expected;
template <class, class, expected_detail::StorageType>
friend struct expected_detail::ExpectedStorage;
friend struct expected_detail::ExpectedHelper;
using Base = expected_detail::ExpectedStorage<Value, Error>;
using MakeBadExpectedAccess =
typename Unexpected<Error>::MakeBadExpectedAccess;
Base& base() & {
return *this;
}
const Base& base() const& {
return *this;
}
Base&& base() && {
return std::move(*this);
}
public:
using value_type = Value;
using error_type = Error;
template <class U>
using rebind = Expected<U, Error>;
static_assert(!std::is_reference<Value>::value,
"Expected may not be used with reference types");
static_assert(!std::is_abstract<Value>::value,
"Expected may not be used with abstract types");
template <class B = Base, class = decltype(B{})>
Expected() noexcept(noexcept(B{})) : Base{} {
}
Expected(const Expected& that) = default;
Expected(Expected&& that) = default;
template <class V,
class E,
bool FollyRequires905 = false,
typename std::enable_if<
(FollyRequires905 ||
static_cast<bool>(
!std::is_same<Expected<V, E>, Expected>::value &&
std::is_constructible<Value, V&&>::value &&
std::is_constructible<Error, E&&>::value)),
int>::type = 0
>
Expected(Expected<V, E> that) : Base{expected_detail::EmptyTag{}} {
this->assign(std::move(that));
}
template <bool FollyRequires913 = false,
typename std::enable_if<
(FollyRequires913 ||
static_cast<bool>(
std::is_copy_constructible<Value>::value)),
int>::type = 0>
constexpr Expected(const Value& val) noexcept(noexcept(Value(val)))
: Base{expected_detail::ValueTag{}, val} {
}
template <bool FollyRequires918 = false,
typename std::enable_if<
(FollyRequires918 ||
static_cast<bool>(
std::is_move_constructible<Value>::value)),
int>::type = 0>
constexpr Expected(Value&& val) noexcept(noexcept(Value(std::move(val))))
: Base{expected_detail::ValueTag{}, std::move(val)} {
}
template <
class T,
bool FollyRequires923 = false,
typename std::enable_if<
(FollyRequires923 ||
static_cast<bool>(std::is_convertible<T, Value>::value &&
!std::is_convertible<T, Error>::value)),
int>::type = 0
>
constexpr Expected(T&& val) noexcept(noexcept(Value(static_cast<T&&>(val))))
: Base{expected_detail::ValueTag{}, static_cast<T&&>(val)} {
}
template <class... Ts,
bool FollyRequires930 = false,
typename std::enable_if<
(FollyRequires930 ||
static_cast<bool>(
std::is_constructible<Value, Ts&&...>::value)),
int>::type = 0>
explicit constexpr Expected(in_place_t, Ts&&... ts) noexcept(
noexcept(Value(std::declval<Ts>()...)))
: Base{expected_detail::ValueTag{}, static_cast<Ts&&>(ts)...} {
}
template <class U,
class... Ts,
bool FollyRequires938 = false,
typename std::enable_if<
(FollyRequires938 ||
static_cast<bool>(
std::is_constructible<Value,
std::initializer_list<U>&,
Ts&&...>::value)),
int>::type = 0
>
explicit constexpr Expected(
in_place_t,
std::initializer_list<U> il,
Ts&&... ts) noexcept(noexcept(Value(std::declval<Ts>()...)))
: Base{expected_detail::ValueTag{}, il, static_cast<Ts&&>(ts)...} {
}
Expected(const Error&) = delete;
Expected(Error&&) = delete;
template <bool FollyRequires952 = false,
typename std::enable_if<
(FollyRequires952 ||
static_cast<bool>(
std::is_copy_constructible<Error>::value)),
int>::type = 0>
constexpr Expected(unexpected_t,
const Error& err) noexcept(noexcept(Error(err)))
: Base{expected_detail::ErrorTag{}, err} {
}
template <bool FollyRequires957 = false,
typename std::enable_if<
(FollyRequires957 ||
static_cast<bool>(
std::is_move_constructible<Error>::value)),
int>::type = 0>
constexpr Expected(unexpected_t,
Error&& err) noexcept(noexcept(Error(std::move(err))))
: Base{expected_detail::ErrorTag{}, std::move(err)} {
}
template <bool FollyRequires962 = false,
typename std::enable_if<
(FollyRequires962 ||
static_cast<bool>(
std::is_copy_constructible<Error>::value)),
int>::type = 0>
constexpr Expected(const Unexpected<Error>& err) noexcept(
noexcept(Error(err.error())))
: Base{expected_detail::ErrorTag{}, err.error()} {
}
template <bool FollyRequires967 = false,
typename std::enable_if<
(FollyRequires967 ||
static_cast<bool>(
std::is_move_constructible<Error>::value)),
int>::type = 0>
constexpr Expected(Unexpected<Error>&& err) noexcept(
noexcept(Error(std::move(err.error()))))
: Base{expected_detail::ErrorTag{}, std::move(err.error())} {
}
Expected& operator=(const Expected& that) = default;
Expected& operator=(Expected&& that) = default;
template <class V,
class E,
bool FollyRequires980 = false,
typename std::enable_if<
(FollyRequires980 ||
static_cast<bool>(
!std::is_same<Expected<V, E>, Expected>::value &&
expected_detail::IsConvertible<V&&,
Value>::value &&
expected_detail::IsConvertible<E&&,
Error>::value)),
int>::type = 0
>
Expected& operator=(Expected<V, E> that) {
this->assign(std::move(that));
return *this;
}
template <bool FollyRequires989 = false,
typename std::enable_if<
(FollyRequires989 ||
static_cast<bool>(
expected_detail::IsCopyable<Value>::value)),
int>::type = 0>
Expected& operator=(const Value& val) noexcept(
expected_detail::IsNothrowCopyable<Value>::value) {
this->assignValue(val);
return *this;
}
template <bool FollyRequires996 = false,
typename std::enable_if<
(FollyRequires996 ||
static_cast<bool>(
expected_detail::IsMovable<Value>::value)),
int>::type = 0>
Expected& operator=(Value&& val) noexcept(
expected_detail::IsNothrowMovable<Value>::value) {
this->assignValue(std::move(val));
return *this;
}
template <
class T,
bool FollyRequires1003 = false,
typename std::enable_if<
(FollyRequires1003 ||
static_cast<bool>(std::is_convertible<T, Value>::value &&
!std::is_convertible<T, Error>::value)),
int>::type = 0
>
Expected& operator=(T&& val) {
this->assignValue(static_cast<T&&>(val));
return *this;
}
template <bool FollyRequires1011 = false,
typename std::enable_if<
(FollyRequires1011 ||
static_cast<bool>(
expected_detail::IsCopyable<Error>::value)),
int>::type = 0>
Expected& operator=(const Unexpected<Error>& err) noexcept(
expected_detail::IsNothrowCopyable<Error>::value) {
this->assignError(err.error());
return *this;
}
template <bool FollyRequires1018 = false,
typename std::enable_if<
(FollyRequires1018 ||
static_cast<bool>(
expected_detail::IsMovable<Error>::value)),
int>::type = 0>
Expected& operator=(Unexpected<Error>&& err) noexcept(
expected_detail::IsNothrowMovable<Error>::value) {
this->assignError(std::move(err.error()));
return *this;
}
Expected(const expected_detail::PromiseReturn<Value, Error>& p)
: Expected{} {
p.promise_->value_ = this;
}
template <class... Ts,
bool FollyRequires1031 = false,
typename std::enable_if<
(FollyRequires1031 ||
static_cast<bool>(
std::is_constructible<Value, Ts&&...>::value)),
int>::type = 0>
void emplace(Ts&&... ts) {
this->assignValue(static_cast<Ts&&>(ts)...);
}
void swap(Expected& that) noexcept(
expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::
value) {
if (this->uninitializedByException() ||
that.uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
using std::swap;
if (*this) {
if (that) {
swap(this->value_, that.value_);
} else {
Error e(std::move(that.error_));
that.assignValue(std::move(this->value_));
this->assignError(std::move(e));
}
} else {
if (!that) {
swap(this->error_, that.error_);
} else {
Error e(std::move(this->error_));
this->assignValue(std::move(that.value_));
that.assignError(std::move(e));
}
}
}
Expected& operator=(const Error&) = delete;
Expected& operator=(Error&&) = delete;
template <class Val, class Err>
friend typename std::enable_if<IsEqualityComparable<Val>::value, bool>::type
operator==(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
template <class Val, class Err>
friend typename std::enable_if<IsLessThanComparable<Val>::value, bool>::type
operator<(const Expected<Val, Err>& lhs, const Expected<Val, Err>& rhs);
constexpr bool hasValue() const noexcept {
return (__builtin_expect(
(expected_detail::Which::eValue == this->which_), 1));
}
constexpr bool hasError() const noexcept {
return (__builtin_expect(
(expected_detail::Which::eError == this->which_), 0));
}
using Base::uninitializedByException;
const Value& value() const& {
requireValue();
return this->Base::value();
}
Value& value() & {
requireValue();
return this->Base::value();
}
Value&& value() && {
requireValue();
return std::move(this->Base::value());
}
const Error& error() const& {
requireError();
return this->Base::error();
}
Error& error() & {
requireError();
return this->Base::error();
}
Error&& error() && {
requireError();
return std::move(this->Base::error());
}
template <class U>
Value value_or(U&& dflt) const& {
if ((__builtin_expect((this->which_ == expected_detail::Which::eValue),
1))) {
return this->value_;
}
return static_cast<U&&>(dflt);
}
template <class U>
Value value_or(U&& dflt) && {
if ((__builtin_expect((this->which_ == expected_detail::Which::eValue),
1))) {
return std::move(this->value_);
}
return static_cast<U&&>(dflt);
}
explicit constexpr operator bool() const noexcept {
return hasValue();
}
const Value& operator*() const& {
return this->value();
}
Value& operator*() & {
return this->value();
}
Value&& operator*() && {
return std::move(this->value());
}
const Value* operator->() const {
return std::addressof(this->value());
}
Value* operator->() {
return std::addressof(this->value());
}
const Value* get_pointer() const& noexcept {
return hasValue() ? std::addressof(this->value_) : nullptr;
}
Value* get_pointer() & noexcept {
return hasValue() ? std::addressof(this->value_) : nullptr;
}
Value* get_pointer() && = delete;
template <class... Fns,
bool FollyRequires1177 = false,
typename std::enable_if<(FollyRequires1177 ||
static_cast<bool>(sizeof...(Fns) >= 1)),
int>::type = 0>
auto then(Fns&&... fns) const& -> decltype(
expected_detail::ExpectedHelper::then_(std::declval<const Base&>(),
std::declval<Fns>()...)) {
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return expected_detail::ExpectedHelper::then_(
base(), static_cast<Fns&&>(fns)...);
}
template <class... Fns,
bool FollyRequires1189 = false,
typename std::enable_if<(FollyRequires1189 ||
static_cast<bool>(sizeof...(Fns) >= 1)),
int>::type = 0>
auto then(Fns&&... fns) & -> decltype(
expected_detail::ExpectedHelper::then_(std::declval<Base&>(),
std::declval<Fns>()...)) {
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return expected_detail::ExpectedHelper::then_(
base(), static_cast<Fns&&>(fns)...);
}
template <class... Fns,
bool FollyRequires1200 = false,
typename std::enable_if<(FollyRequires1200 ||
static_cast<bool>(sizeof...(Fns) >= 1)),
int>::type = 0>
auto then(Fns&&... fns) && -> decltype(
expected_detail::ExpectedHelper::then_(std::declval<Base&&>(),
std::declval<Fns>()...)) {
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return expected_detail::ExpectedHelper::then_(
std::move(base()), static_cast<Fns&&>(fns)...);
}
template <class Yes, class No = MakeBadExpectedAccess>
auto thenOrThrow(Yes&& yes, No&& no = No{}) const& -> decltype(
std::declval<Yes>()(std::declval<const Value&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<const Value&>()));
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
}
template <class Yes, class No = MakeBadExpectedAccess>
auto thenOrThrow(Yes&& yes, No&& no = No{}) & -> decltype(
std::declval<Yes>()(std::declval<Value&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<Value&>()));
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
base(), static_cast<Yes&&>(yes), static_cast<No&&>(no)));
}
template <class Yes, class No = MakeBadExpectedAccess>
auto thenOrThrow(Yes&& yes, No&& no = No{}) && -> decltype(
std::declval<Yes>()(std::declval<Value&&>())) {
using Ret = decltype(std::declval<Yes>()(std::declval<Value&&>()));
if (this->uninitializedByException()) {
throw_exception<BadExpectedAccess>();
}
return Ret(expected_detail::ExpectedHelper::thenOrThrow_(
std::move(base()),
static_cast<Yes&&>(yes),
static_cast<No&&>(no)));
}
private:
void requireValue() const {
if ((__builtin_expect((!hasValue()), 0))) {
if ((__builtin_expect((hasError()), 1))) {
using Err = typename Unexpected<Error>::BadExpectedAccess;
throw_exception<Err>(this->error_);
}
throw_exception<BadExpectedAccess>();
}
}
void requireError() const {
if ((__builtin_expect((!hasError()), 0))) {
throw_exception<BadExpectedAccess>();
}
}
expected_detail::Which which() const noexcept {
return this->which_;
}
};
template <class Value, class Error>
inline typename std::enable_if<IsEqualityComparable<Value>::value, bool>::type
operator==(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
if ((__builtin_expect((lhs.uninitializedByException()), 0))) {
throw_exception<BadExpectedAccess>();
}
if ((__builtin_expect((lhs.which_ != rhs.which_), 0))) {
return false;
}
if ((__builtin_expect((lhs.hasError()), 0))) {
return true;
}
return lhs.value_ == rhs.value_;
}
template <class Value,
class Error,
bool FollyRequires1288 = false,
typename std::enable_if<
(FollyRequires1288 ||
static_cast<bool>(IsEqualityComparable<Value>::value)),
int>::type = 0>
inline bool operator!=(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
return !(rhs == lhs);
}
template <class Value, class Error>
inline typename std::enable_if<IsLessThanComparable<Value>::value, bool>::type
operator<(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
if ((__builtin_expect((lhs.uninitializedByException() ||
rhs.uninitializedByException()),
0))) {
throw_exception<BadExpectedAccess>();
}
if ((__builtin_expect((lhs.hasError()), 0))) {
return !rhs.hasError();
}
if ((__builtin_expect((rhs.hasError()), 0))) {
return false;
}
return lhs.value_ < rhs.value_;
}
template <class Value,
class Error,
bool FollyRequires1315 = false,
typename std::enable_if<
(FollyRequires1315 ||
static_cast<bool>(IsLessThanComparable<Value>::value)),
int>::type = 0>
inline bool operator<=(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
return !(rhs < lhs);
}
template <class Value,
class Error,
bool FollyRequires1324 = false,
typename std::enable_if<
(FollyRequires1324 ||
static_cast<bool>(IsLessThanComparable<Value>::value)),
int>::type = 0>
inline bool operator>(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
return rhs < lhs;
}
template <class Value,
class Error,
bool FollyRequires1333 = false,
typename std::enable_if<
(FollyRequires1333 ||
static_cast<bool>(IsLessThanComparable<Value>::value)),
int>::type = 0>
inline bool operator>=(const Expected<Value, Error>& lhs,
const Expected<Value, Error>& rhs) {
return !(lhs < rhs);
}
template <class Value, class Error>
void swap(Expected<Value, Error>& lhs, Expected<Value, Error>& rhs) noexcept(
expected_detail::StrictAllOf<IsNothrowSwappable, Value, Error>::value) {
lhs.swap(rhs);
}
template <class Value, class Error>
const Value* get_pointer(const Expected<Value, Error>& ex) noexcept {
return ex.get_pointer();
}
template <class Value, class Error>
Value* get_pointer(Expected<Value, Error>& ex) noexcept {
return ex.get_pointer();
}
// # 1369 "tlm/deps/folly.exploded/include/folly/Expected.h" 3 4
template <class Error, class Value>
constexpr Expected<typename std::decay<Value>::type, Error> makeExpected(
Value&& val) {
return Expected<typename std::decay<Value>::type, Error>{
in_place, static_cast<Value&&>(val)};
}
template <class Value, class Error>
bool operator==(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator!=(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator<(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator<=(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator>=(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator>(const Expected<Value, Error>&, const Value& other) = delete;
template <class Value, class Error>
bool operator==(const Value& other, const Expected<Value, Error>&) = delete;
template <class Value, class Error>
bool operator!=(const Value& other, const Expected<Value, Error>&) = delete;
template <class Value, class Error>
bool operator<(const Value& other, const Expected<Value, Error>&) = delete;
template <class Value, class Error>
bool operator<=(const Value& other, const Expected<Value, Error>&) = delete;
template <class Value, class Error>
bool operator>=(const Value& other, const Expected<Value, Error>&) = delete;
template <class Value, class Error>
bool operator>(const Value& other, const Expected<Value, Error>&) = delete;
} // namespace folly
// # 118 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Range.h" 1 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/CString.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/CString.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/lang/CString.h" 2 3 4
namespace folly {
namespace detail {
void* memrchr_fallback(void* s, int c, std::size_t len) noexcept;
void const* memrchr_fallback(void const* s, int c, std::size_t len) noexcept;
} // namespace detail
void* memrchr(void* s, int c, std::size_t len) noexcept;
void const* memrchr(void const* s, int c, std::size_t len) noexcept;
std::size_t strlcpy(char* dest, char const* src, std::size_t size);
} // namespace folly
// # 25 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Constexpr.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Constexpr.h" 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/portability/Constexpr.h" 2 3 4
namespace folly {
namespace detail {
template <typename Char>
constexpr size_t constexpr_strlen_internal(const Char* s, size_t len) {
return *(s + 0) == Char(0)
? len + 0
: *(s + 1) == Char(0)
? len + 1
: *(s + 2) == Char(0)
? len + 2
: *(s + 3) == Char(0)
? len + 3
: *(s + 4) == Char(0)
? len + 4
: *(s + 5) == Char(0)
? len + 5
: *(s +
6) == Char(0)
? len + 6
: *(s +
7) == Char(0)
? len + 7
: constexpr_strlen_internal(
s + 8,
len + 8);
}
static_assert(constexpr_strlen_internal("123456789", 0) == 9,
"Someone appears to have broken constexpr_strlen...");
template <typename Char>
constexpr int constexpr_strcmp_internal(const Char* s1, const Char* s2) {
return (*s1 == '\0' || *s1 != *s2)
? (static_cast<int>(*s1 - *s2))
: constexpr_strcmp_internal(s1 + 1, s2 + 1);
}
} // namespace detail
template <typename Char>
constexpr size_t constexpr_strlen(const Char* s) {
return detail::constexpr_strlen_internal(s, 0);
}
template <>
constexpr size_t constexpr_strlen(const char* s) {
return std::strlen(s);
}
template <typename Char>
constexpr int constexpr_strcmp(const Char* s1, const Char* s2) {
return detail::constexpr_strcmp_internal(s1, s2);
}
template <>
constexpr int constexpr_strcmp(const char* s1, const char* s2) {
return std::strcmp(s1, s2);
}
} // namespace folly
// # 27 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 31 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 32 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 34 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 44 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/CpuId.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/CpuId.h" 3 4
// # 27 "tlm/deps/folly.exploded/include/folly/CpuId.h" 3 4
namespace folly {
class CpuId {
public:
inline __attribute__((__always_inline__)) CpuId() {
// # 92 "tlm/deps/folly.exploded/include/folly/CpuId.h" 3 4
uint32_t n;
__asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
if (n >= 1) {
uint32_t f1a;
__asm__("cpuid"
: "=a"(f1a), "=c"(f1c_), "=d"(f1d_)
: "a"(1)
: "ebx");
}
if (n >= 7) {
uint32_t f7a;
__asm__("cpuid"
: "=a"(f7a), "=b"(f7b_), "=c"(f7c_)
: "a"(7), "c"(0)
: "edx");
}
}
// # 115 "tlm/deps/folly.exploded/include/folly/CpuId.h" 3 4
inline __attribute__((__always_inline__)) bool sse3() const {
return ((f1c_) & (1U << 0)) != 0;
}
inline __attribute__((__always_inline__)) bool pclmuldq() const {
return ((f1c_) & (1U << 1)) != 0;
}
inline __attribute__((__always_inline__)) bool dtes64() const {
return ((f1c_) & (1U << 2)) != 0;
}
inline __attribute__((__always_inline__)) bool monitor() const {
return ((f1c_) & (1U << 3)) != 0;
}
inline __attribute__((__always_inline__)) bool dscpl() const {
return ((f1c_) & (1U << 4)) != 0;
}
inline __attribute__((__always_inline__)) bool vmx() const {
return ((f1c_) & (1U << 5)) != 0;
}
inline __attribute__((__always_inline__)) bool smx() const {
return ((f1c_) & (1U << 6)) != 0;
}
inline __attribute__((__always_inline__)) bool eist() const {
return ((f1c_) & (1U << 7)) != 0;
}
inline __attribute__((__always_inline__)) bool tm2() const {
return ((f1c_) & (1U << 8)) != 0;
}
inline __attribute__((__always_inline__)) bool ssse3() const {
return ((f1c_) & (1U << 9)) != 0;
}
inline __attribute__((__always_inline__)) bool cnxtid() const {
return ((f1c_) & (1U << 10)) != 0;
}
inline __attribute__((__always_inline__)) bool fma() const {
return ((f1c_) & (1U << 12)) != 0;
}
inline __attribute__((__always_inline__)) bool cx16() const {
return ((f1c_) & (1U << 13)) != 0;
}
inline __attribute__((__always_inline__)) bool xtpr() const {
return ((f1c_) & (1U << 14)) != 0;
}
inline __attribute__((__always_inline__)) bool pdcm() const {
return ((f1c_) & (1U << 15)) != 0;
}
inline __attribute__((__always_inline__)) bool pcid() const {
return ((f1c_) & (1U << 17)) != 0;
}
inline __attribute__((__always_inline__)) bool dca() const {
return ((f1c_) & (1U << 18)) != 0;
}
inline __attribute__((__always_inline__)) bool sse41() const {
return ((f1c_) & (1U << 19)) != 0;
}
inline __attribute__((__always_inline__)) bool sse42() const {
return ((f1c_) & (1U << 20)) != 0;
}
inline __attribute__((__always_inline__)) bool x2apic() const {
return ((f1c_) & (1U << 21)) != 0;
}
inline __attribute__((__always_inline__)) bool movbe() const {
return ((f1c_) & (1U << 22)) != 0;
}
inline __attribute__((__always_inline__)) bool popcnt() const {
return ((f1c_) & (1U << 23)) != 0;
}
inline __attribute__((__always_inline__)) bool tscdeadline() const {
return ((f1c_) & (1U << 24)) != 0;
}
inline __attribute__((__always_inline__)) bool aes() const {
return ((f1c_) & (1U << 25)) != 0;
}
inline __attribute__((__always_inline__)) bool xsave() const {
return ((f1c_) & (1U << 26)) != 0;
}
inline __attribute__((__always_inline__)) bool osxsave() const {
return ((f1c_) & (1U << 27)) != 0;
}
inline __attribute__((__always_inline__)) bool avx() const {
return ((f1c_) & (1U << 28)) != 0;
}
inline __attribute__((__always_inline__)) bool f16c() const {
return ((f1c_) & (1U << 29)) != 0;
}
inline __attribute__((__always_inline__)) bool rdrand() const {
return ((f1c_) & (1U << 30)) != 0;
}
inline __attribute__((__always_inline__)) bool fpu() const {
return ((f1d_) & (1U << 0)) != 0;
}
inline __attribute__((__always_inline__)) bool vme() const {
return ((f1d_) & (1U << 1)) != 0;
}
inline __attribute__((__always_inline__)) bool de() const {
return ((f1d_) & (1U << 2)) != 0;
}
inline __attribute__((__always_inline__)) bool pse() const {
return ((f1d_) & (1U << 3)) != 0;
}
inline __attribute__((__always_inline__)) bool tsc() const {
return ((f1d_) & (1U << 4)) != 0;
}
inline __attribute__((__always_inline__)) bool msr() const {
return ((f1d_) & (1U << 5)) != 0;
}
inline __attribute__((__always_inline__)) bool pae() const {
return ((f1d_) & (1U << 6)) != 0;
}
inline __attribute__((__always_inline__)) bool mce() const {
return ((f1d_) & (1U << 7)) != 0;
}
inline __attribute__((__always_inline__)) bool cx8() const {
return ((f1d_) & (1U << 8)) != 0;
}
inline __attribute__((__always_inline__)) bool apic() const {
return ((f1d_) & (1U << 9)) != 0;
}
inline __attribute__((__always_inline__)) bool sep() const {
return ((f1d_) & (1U << 11)) != 0;
}
inline __attribute__((__always_inline__)) bool mtrr() const {
return ((f1d_) & (1U << 12)) != 0;
}
inline __attribute__((__always_inline__)) bool pge() const {
return ((f1d_) & (1U << 13)) != 0;
}
inline __attribute__((__always_inline__)) bool mca() const {
return ((f1d_) & (1U << 14)) != 0;
}
inline __attribute__((__always_inline__)) bool cmov() const {
return ((f1d_) & (1U << 15)) != 0;
}
inline __attribute__((__always_inline__)) bool pat() const {
return ((f1d_) & (1U << 16)) != 0;
}
inline __attribute__((__always_inline__)) bool pse36() const {
return ((f1d_) & (1U << 17)) != 0;
}
inline __attribute__((__always_inline__)) bool psn() const {
return ((f1d_) & (1U << 18)) != 0;
}
inline __attribute__((__always_inline__)) bool clfsh() const {
return ((f1d_) & (1U << 19)) != 0;
}
inline __attribute__((__always_inline__)) bool ds() const {
return ((f1d_) & (1U << 21)) != 0;
}
inline __attribute__((__always_inline__)) bool acpi() const {
return ((f1d_) & (1U << 22)) != 0;
}
inline __attribute__((__always_inline__)) bool mmx() const {
return ((f1d_) & (1U << 23)) != 0;
}
inline __attribute__((__always_inline__)) bool fxsr() const {
return ((f1d_) & (1U << 24)) != 0;
}
inline __attribute__((__always_inline__)) bool sse() const {
return ((f1d_) & (1U << 25)) != 0;
}
inline __attribute__((__always_inline__)) bool sse2() const {
return ((f1d_) & (1U << 26)) != 0;
}
inline __attribute__((__always_inline__)) bool ss() const {
return ((f1d_) & (1U << 27)) != 0;
}
inline __attribute__((__always_inline__)) bool htt() const {
return ((f1d_) & (1U << 28)) != 0;
}
inline __attribute__((__always_inline__)) bool tm() const {
return ((f1d_) & (1U << 29)) != 0;
}
inline __attribute__((__always_inline__)) bool pbe() const {
return ((f1d_) & (1U << 31)) != 0;
}
inline __attribute__((__always_inline__)) bool bmi1() const {
return ((f7b_) & (1U << 3)) != 0;
}
inline __attribute__((__always_inline__)) bool hle() const {
return ((f7b_) & (1U << 4)) != 0;
}
inline __attribute__((__always_inline__)) bool avx2() const {
return ((f7b_) & (1U << 5)) != 0;
}
inline __attribute__((__always_inline__)) bool smep() const {
return ((f7b_) & (1U << 7)) != 0;
}
inline __attribute__((__always_inline__)) bool bmi2() const {
return ((f7b_) & (1U << 8)) != 0;
}
inline __attribute__((__always_inline__)) bool erms() const {
return ((f7b_) & (1U << 9)) != 0;
}
inline __attribute__((__always_inline__)) bool invpcid() const {
return ((f7b_) & (1U << 10)) != 0;
}
inline __attribute__((__always_inline__)) bool rtm() const {
return ((f7b_) & (1U << 11)) != 0;
}
inline __attribute__((__always_inline__)) bool mpx() const {
return ((f7b_) & (1U << 14)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512f() const {
return ((f7b_) & (1U << 16)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512dq() const {
return ((f7b_) & (1U << 17)) != 0;
}
inline __attribute__((__always_inline__)) bool rdseed() const {
return ((f7b_) & (1U << 18)) != 0;
}
inline __attribute__((__always_inline__)) bool adx() const {
return ((f7b_) & (1U << 19)) != 0;
}
inline __attribute__((__always_inline__)) bool smap() const {
return ((f7b_) & (1U << 20)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512ifma() const {
return ((f7b_) & (1U << 21)) != 0;
}
inline __attribute__((__always_inline__)) bool pcommit() const {
return ((f7b_) & (1U << 22)) != 0;
}
inline __attribute__((__always_inline__)) bool clflushopt() const {
return ((f7b_) & (1U << 23)) != 0;
}
inline __attribute__((__always_inline__)) bool clwb() const {
return ((f7b_) & (1U << 24)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512pf() const {
return ((f7b_) & (1U << 26)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512er() const {
return ((f7b_) & (1U << 27)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512cd() const {
return ((f7b_) & (1U << 28)) != 0;
}
inline __attribute__((__always_inline__)) bool sha() const {
return ((f7b_) & (1U << 29)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512bw() const {
return ((f7b_) & (1U << 30)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512vl() const {
return ((f7b_) & (1U << 31)) != 0;
}
inline __attribute__((__always_inline__)) bool prefetchwt1() const {
return ((f7c_) & (1U << 0)) != 0;
}
inline __attribute__((__always_inline__)) bool avx512vbmi() const {
return ((f7c_) & (1U << 1)) != 0;
}
inline __attribute__((__always_inline__)) bool vaes() const {
return ((f7c_) & (1U << 9)) != 0;
}
inline __attribute__((__always_inline__)) bool vpclmulqdq() const {
return ((f7c_) & (1U << 10)) != 0;
}
private:
uint32_t f1c_ = 0;
uint32_t f1d_ = 0;
uint32_t f7b_ = 0;
uint32_t f7c_ = 0;
};
} // namespace folly
// # 45 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/RangeCommon.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/RangeCommon.h" 3 4
// # 21 "tlm/deps/folly.exploded/include/folly/detail/RangeCommon.h" 2 3 4
namespace folly {
namespace detail {
// # 36 "tlm/deps/folly.exploded/include/folly/detail/RangeCommon.h" 3 4
class StringPieceLite {
public:
StringPieceLite(const char* b, const char* e) : b_(b), e_(e) {
}
template <typename Range>
StringPieceLite(const Range& r)
: StringPieceLite(r.data(), r.data() + r.size()) {
}
const char* data() const {
return b_;
}
const char* begin() const {
return b_;
}
const char* end() const {
return e_;
}
size_t size() const {
return size_t(e_ - b_);
}
bool empty() const {
return size() == 0;
}
const char& operator[](size_t i) const {
(static_cast<bool>(size() > i)
? void(0)
: __assert_fail("size() > i",
"tlm/deps/folly.exploded/include/folly/detail/"
"RangeCommon.h",
58,
__extension__ __PRETTY_FUNCTION__));
return b_[i];
}
template <typename Range>
explicit operator Range() const {
return Range(begin(), end());
}
private:
const char* b_;
const char* e_;
};
inline size_t qfind_first_byte_of_std(const StringPieceLite haystack,
const StringPieceLite needles) {
auto ret = std::find_first_of(haystack.begin(),
haystack.end(),
needles.begin(),
needles.end(),
[](char a, char b) { return a == b; });
return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
}
size_t qfind_first_byte_of_bitset(const StringPieceLite haystack,
const StringPieceLite needles);
size_t qfind_first_byte_of_byteset(const StringPieceLite haystack,
const StringPieceLite needles);
inline size_t qfind_first_byte_of_nosse(const StringPieceLite haystack,
const StringPieceLite needles) {
if ((__builtin_expect((needles.empty() || haystack.empty()), 0))) {
return std::string::npos;
}
if ((needles.size() >= 4 && haystack.size() <= 10) ||
(needles.size() >= 16 && haystack.size() <= 64) ||
needles.size() >= 32) {
return qfind_first_byte_of_byteset(haystack, needles);
}
return qfind_first_byte_of_std(haystack, needles);
}
} // namespace detail
} // namespace folly
// # 48 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/RangeSse42.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/RangeSse42.h" 3 4
namespace folly {
namespace detail {
size_t qfind_first_byte_of_sse42(const StringPieceLite haystack,
const StringPieceLite needles);
}
} // namespace folly
// # 49 "tlm/deps/folly.exploded/include/folly/Range.h" 2 3 4
// # 51 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
#pragma GCC diagnostic push
// # 51 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
// # 52 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
#pragma GCC diagnostic ignored "-Wshadow"
// # 52 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
namespace folly {
template <class T>
struct IsSomeString : std::false_type {};
template <typename Alloc>
struct IsSomeString<std::basic_string<char, std::char_traits<char>, Alloc>>
: std::true_type {};
template <class Iter>
class Range;
template <class Iter,
class Comp = std::equal_to<typename Range<Iter>::value_type>>
inline size_t qfind(const Range<Iter>& haystack,
const Range<Iter>& needle,
Comp eq = Comp());
template <class Iter>
size_t qfind(const Range<Iter>& haystack,
const typename Range<Iter>::value_type& needle);
template <class Iter>
size_t rfind(const Range<Iter>& haystack,
const typename Range<Iter>::value_type& needle);
template <class Iter>
inline size_t qfind_first_of(const Range<Iter>& haystack,
const Range<Iter>& needle);
namespace detail {
template <class T>
struct IsCharPointer {};
template <>
struct IsCharPointer<char*> {
typedef int type;
};
template <>
struct IsCharPointer<const char*> {
typedef int const_type;
typedef int type;
};
} // namespace detail
// # 146 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
template <class Iter>
class Range {
private:
template <typename Alloc>
using string = std::basic_string<char, std::char_traits<char>, Alloc>;
public:
typedef std::size_t size_type;
typedef Iter iterator;
typedef Iter const_iterator;
typedef typename std::remove_reference<
typename std::iterator_traits<Iter>::reference>::type value_type;
using difference_type =
typename std::iterator_traits<Iter>::difference_type;
typedef typename std::iterator_traits<Iter>::reference reference;
typedef typename std::conditional<
std::is_same<Iter, char*>::value ||
std::is_same<Iter, unsigned char*>::value,
Range<const value_type*>,
Range<Iter>>::type const_range_type;
typedef std::char_traits<typename std::remove_const<value_type>::type>
traits_type;
static const size_type npos;
constexpr Range() : b_(), e_() {
}
constexpr Range(const Range&) = default;
constexpr Range(Range&&) = default;
public:
constexpr Range(Iter start, Iter end) : b_(start), e_(end) {
}
constexpr Range(Iter start, size_t size) : b_(start), e_(start + size) {
}
Range(std::nullptr_t) = delete;
constexpr Range(Iter str) : b_(str), e_(str + constexpr_strlen(str)) {
static_assert(
std::is_same<int,
typename detail::IsCharPointer<Iter>::type>::value,
"This constructor is only available for character ranges");
}
template <class Alloc,
class T = Iter,
typename detail::IsCharPointer<T>::const_type = 0>
Range(const string<Alloc>& str) : b_(str.data()), e_(b_ + str.size()) {
}
template <class Alloc,
class T = Iter,
typename detail::IsCharPointer<T>::const_type = 0>
Range(const string<Alloc>& str,
typename string<Alloc>::size_type startFrom) {
if ((__builtin_expect((startFrom > str.size()), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
b_ = str.data() + startFrom;
e_ = str.data() + str.size();
}
template <class Alloc,
class T = Iter,
typename detail::IsCharPointer<T>::const_type = 0>
Range(const string<Alloc>& str,
typename string<Alloc>::size_type startFrom,
typename string<Alloc>::size_type size) {
if ((__builtin_expect((startFrom > str.size()), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
b_ = str.data() + startFrom;
if (str.size() - startFrom < size) {
e_ = str.data() + str.size();
} else {
e_ = b_ + size;
}
}
Range(const Range& other, size_type first, size_type length = npos)
: Range(other.subpiece(first, length)) {
}
template <class Container,
class = typename std::enable_if<std::is_same<
Iter,
typename Container::const_pointer>::value>::type,
class = decltype(Iter(std::declval<Container const&>().data()),
Iter(std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
constexpr Range(Container const& container)
: b_(container.data()), e_(b_ + container.size()) {
}
template <class Container,
class = typename std::enable_if<std::is_same<
Iter,
typename Container::const_pointer>::value>::type,
class = decltype(Iter(std::declval<Container const&>().data()),
Iter(std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
Range(Container const& container, typename Container::size_type startFrom) {
auto const cdata = container.data();
auto const csize = container.size();
if ((__builtin_expect((startFrom > csize), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
b_ = cdata + startFrom;
e_ = cdata + csize;
}
template <class Container,
class = typename std::enable_if<std::is_same<
Iter,
typename Container::const_pointer>::value>::type,
class = decltype(Iter(std::declval<Container const&>().data()),
Iter(std::declval<Container const&>().data() +
std::declval<Container const&>().size()))>
Range(Container const& container,
typename Container::size_type startFrom,
typename Container::size_type size) {
auto const cdata = container.data();
auto const csize = container.size();
if ((__builtin_expect((startFrom > csize), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
b_ = cdata + startFrom;
if (csize - startFrom < size) {
e_ = cdata + csize;
} else {
e_ = b_ + size;
}
}
template <class OtherIter,
typename std::enable_if<
(std::is_same<Iter, const unsigned char*>::value &&
(std::is_same<OtherIter, const char*>::value ||
std::is_same<OtherIter, char*>::value)),
int>::type = 0>
Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<const unsigned char*>(other.begin())),
e_(reinterpret_cast<const unsigned char*>(other.end())) {
}
template <class OtherIter,
typename std::enable_if<
(std::is_same<Iter, unsigned char*>::value &&
std::is_same<OtherIter, char*>::value),
int>::type = 0>
Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<unsigned char*>(other.begin())),
e_(reinterpret_cast<unsigned char*>(other.end())) {
}
template <class OtherIter,
typename std::enable_if<
(std::is_same<Iter, const char*>::value &&
(std::is_same<OtherIter, const unsigned char*>::value ||
std::is_same<OtherIter, unsigned char*>::value)),
int>::type = 0>
explicit Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<const char*>(other.begin())),
e_(reinterpret_cast<const char*>(other.end())) {
}
template <class OtherIter,
typename std::enable_if<
(std::is_same<Iter, char*>::value &&
std::is_same<OtherIter, unsigned char*>::value),
int>::type = 0>
explicit Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<char*>(other.begin())),
e_(reinterpret_cast<char*>(other.end())) {
}
template <class OtherIter,
typename std::enable_if<
(!std::is_same<Iter, OtherIter>::value &&
std::is_convertible<OtherIter, Iter>::value),
int>::type = 0>
constexpr Range(const Range<OtherIter>& other)
: b_(other.begin()), e_(other.end()) {
}
template <class OtherIter,
typename std::enable_if<
(!std::is_same<Iter, OtherIter>::value &&
!std::is_convertible<OtherIter, Iter>::value &&
std::is_constructible<Iter, const OtherIter&>::value),
int>::type = 0>
constexpr explicit Range(const Range<OtherIter>& other)
: b_(other.begin()), e_(other.end()) {
}
// # 374 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
template <class T,
size_t N,
typename = typename std::enable_if<
std::is_convertible<const T*, Iter>::value>::type>
constexpr explicit Range(const std::array<T, N>& array)
: b_{array.empty() ? nullptr : &array.at(0)},
e_{array.empty() ? nullptr : &array.at(0) + N} {
}
template <class T,
size_t N,
typename = typename std::enable_if<
std::is_convertible<T*, Iter>::value>::type>
constexpr explicit Range(std::array<T, N>& array)
: b_{array.empty() ? nullptr : &array.at(0)},
e_{array.empty() ? nullptr : &array.at(0) + N} {
}
Range& operator=(const Range& rhs) & = default;
Range& operator=(Range&& rhs) & = default;
template <class Alloc,
class T = Iter,
typename detail::IsCharPointer<T>::const_type = 0>
Range& operator=(string<Alloc>&& rhs) = delete;
void clear() {
b_ = Iter();
e_ = Iter();
}
void assign(Iter start, Iter end) {
b_ = start;
e_ = end;
}
void reset(Iter start, size_type size) {
b_ = start;
e_ = start + size;
}
template <typename Alloc>
void reset(const string<Alloc>& str) {
reset(str.data(), str.size());
}
constexpr size_type size() const {
(static_cast<bool>(b_ <= e_)
? void(0)
: __assert_fail(
"b_ <= e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
423,
__extension__ __PRETTY_FUNCTION__));
return size_type(e_ - b_);
}
constexpr size_type walk_size() const {
return size_type(std::distance(b_, e_));
}
constexpr bool empty() const {
return b_ == e_;
}
constexpr Iter data() const {
return b_;
}
constexpr Iter start() const {
return b_;
}
constexpr Iter begin() const {
return b_;
}
constexpr Iter end() const {
return e_;
}
constexpr Iter cbegin() const {
return b_;
}
constexpr Iter cend() const {
return e_;
}
value_type& front() {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
452,
__extension__ __PRETTY_FUNCTION__));
return *b_;
}
value_type& back() {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
456,
__extension__ __PRETTY_FUNCTION__));
return *std::prev(e_);
}
const value_type& front() const {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
460,
__extension__ __PRETTY_FUNCTION__));
return *b_;
}
const value_type& back() const {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
464,
__extension__ __PRETTY_FUNCTION__));
return *std::prev(e_);
}
private:
// # 486 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
struct NotStringView {};
template <typename ValueType>
struct StringViewType
: std::conditional<
std::is_pod<std::remove_const_t<ValueType>>::value,
std::basic_string_view<std::remove_const_t<ValueType>>,
NotStringView> {};
template <typename Target>
struct IsConstructibleViaStringView
: Conjunction<std::is_constructible<_t<StringViewType<value_type>>,
Iter const&,
size_type>,
std::is_constructible<Target,
_t<StringViewType<value_type>>>> {};
public:
template <
typename Tgt,
std::enable_if_t<
std::is_constructible<Tgt, Iter const&, size_type>::value &&
!IsConstructibleViaStringView<Tgt>::value,
int> = 0>
constexpr explicit operator Tgt() const noexcept(
std::is_nothrow_constructible<Tgt, Iter const&, size_type>::value) {
return Tgt(b_, walk_size());
}
template <typename Tgt,
std::enable_if_t<
!std::is_constructible<Tgt, Iter const&, size_type>::
value &&
std::is_constructible<Tgt,
Iter const&,
Iter const&>::value &&
!IsConstructibleViaStringView<Tgt>::value,
int> = 0>
constexpr explicit operator Tgt() const
noexcept(std::is_nothrow_constructible<Tgt,
Iter const&,
Iter const&>::value) {
return Tgt(b_, e_);
}
template <
typename Tgt,
typename ValueType = value_type,
std::enable_if_t<
StrictConjunction<
std::is_same<Tgt, _t<StringViewType<ValueType>>>,
std::is_constructible<_t<StringViewType<ValueType>>,
Iter const&,
size_type>>::value,
int> = 0>
constexpr operator Tgt() const noexcept(
std::is_nothrow_constructible<Tgt, Iter const&, size_type>::value) {
return Tgt(b_, walk_size());
}
// # 569 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
template <typename Tgt, typename... Args>
constexpr std::enable_if_t<
std::is_constructible<Tgt, Iter const&, size_type>::value,
Tgt>
to(Args&&... args) const
noexcept(std::is_nothrow_constructible<Tgt,
Iter const&,
size_type,
Args&&...>::value) {
return Tgt(b_, walk_size(), static_cast<Args&&>(args)...);
}
template <typename Tgt, typename... Args>
constexpr std::enable_if_t<
!std::is_constructible<Tgt, Iter const&, size_type>::value &&
std::is_constructible<Tgt, Iter const&, Iter const&>::value,
Tgt>
to(Args&&... args) const
noexcept(std::is_nothrow_constructible<Tgt,
Iter const&,
Iter const&,
Args&&...>::value) {
return Tgt(b_, e_, static_cast<Args&&>(args)...);
}
std::string str() const {
return to<std::string>();
}
std::string toString() const {
return to<std::string>();
}
const_range_type castToConst() const {
return const_range_type(*this);
}
int compare(const const_range_type& o) const {
const size_type tsize = this->size();
const size_type osize = o.size();
const size_type msize = std::min(tsize, osize);
int r = traits_type::compare(data(), o.data(), msize);
if (r == 0 && tsize != osize) {
r = (static_cast<int>((osize - tsize) >> (8 * sizeof(size_t) - 1))
<< 1) -
1;
}
return r;
}
value_type& operator[](size_t i) {
(static_cast<bool>(i < size())
? void(0)
: __assert_fail(
"i < size()",
"tlm/deps/folly.exploded/include/folly/Range.h",
618,
__extension__ __PRETTY_FUNCTION__));
return b_[i];
}
const value_type& operator[](size_t i) const {
(static_cast<bool>(i < size())
? void(0)
: __assert_fail(
"i < size()",
"tlm/deps/folly.exploded/include/folly/Range.h",
623,
__extension__ __PRETTY_FUNCTION__));
return b_[i];
}
value_type& at(size_t i) {
if (i >= size()) {
throw_exception<std::out_of_range>("index out of range");
}
return b_[i];
}
const value_type& at(size_t i) const {
if (i >= size()) {
throw_exception<std::out_of_range>("index out of range");
}
return b_[i];
}
// # 659 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
[[deprecated(
"Replace with folly::Hash if the hash is not serialized")]] uint32_t
hash() const {
uint32_t hash = 5381;
for (size_t ix = 0; ix < size(); ix++) {
hash = ((hash << 5) + hash) + b_[ix];
}
return hash;
}
void advance(size_type n) {
if ((__builtin_expect((n > size()), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
b_ += n;
}
void subtract(size_type n) {
if ((__builtin_expect((n > size()), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
e_ -= n;
}
Range subpiece(size_type first, size_type length = npos) const {
if ((__builtin_expect((first > size()), 0))) {
throw_exception<std::out_of_range>("index out of range");
}
return Range(b_ + first, std::min(length, size() - first));
}
void uncheckedAdvance(size_type n) {
(static_cast<bool>(n <= size())
? void(0)
: __assert_fail(
"n <= size()",
"tlm/deps/folly.exploded/include/folly/Range.h",
695,
__extension__ __PRETTY_FUNCTION__));
b_ += n;
}
void uncheckedSubtract(size_type n) {
(static_cast<bool>(n <= size())
? void(0)
: __assert_fail(
"n <= size()",
"tlm/deps/folly.exploded/include/folly/Range.h",
700,
__extension__ __PRETTY_FUNCTION__));
e_ -= n;
}
Range uncheckedSubpiece(size_type first, size_type length = npos) const {
(static_cast<bool>(first <= size())
? void(0)
: __assert_fail(
"first <= size()",
"tlm/deps/folly.exploded/include/folly/Range.h",
705,
__extension__ __PRETTY_FUNCTION__));
return Range(b_ + first, std::min(length, size() - first));
}
void pop_front() {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
710,
__extension__ __PRETTY_FUNCTION__));
++b_;
}
void pop_back() {
(static_cast<bool>(b_ < e_)
? void(0)
: __assert_fail(
"b_ < e_",
"tlm/deps/folly.exploded/include/folly/Range.h",
715,
__extension__ __PRETTY_FUNCTION__));
--e_;
}
size_type find(const_range_type str) const {
return qfind(castToConst(), str);
}
size_type find(const_range_type str, size_t pos) const {
if (pos > size()) {
return std::string::npos;
}
size_t ret = qfind(castToConst().subpiece(pos), str);
return ret == npos ? ret : ret + pos;
}
size_type find(Iter s, size_t pos, size_t n) const {
if (pos > size()) {
return std::string::npos;
}
auto forFinding = castToConst();
size_t ret = qfind(pos ? forFinding.subpiece(pos) : forFinding,
const_range_type(s, n));
return ret == npos ? ret : ret + pos;
}
size_type find(const Iter s) const {
return qfind(castToConst(), const_range_type(s));
}
size_type find(const Iter s, size_t pos) const {
if (pos > size()) {
return std::string::npos;
}
size_type ret = qfind(castToConst().subpiece(pos), const_range_type(s));
return ret == npos ? ret : ret + pos;
}
size_type find(value_type c) const {
return qfind(castToConst(), c);
}
size_type rfind(value_type c) const {
return folly::rfind(castToConst(), c);
}
size_type find(value_type c, size_t pos) const {
if (pos > size()) {
return std::string::npos;
}
size_type ret = qfind(castToConst().subpiece(pos), c);
return ret == npos ? ret : ret + pos;
}
size_type find_first_of(const_range_type needles) const {
return qfind_first_of(castToConst(), needles);
}
size_type find_first_of(const_range_type needles, size_t pos) const {
if (pos > size()) {
return std::string::npos;
}
size_type ret = qfind_first_of(castToConst().subpiece(pos), needles);
return ret == npos ? ret : ret + pos;
}
size_type find_first_of(Iter needles) const {
return find_first_of(const_range_type(needles));
}
size_type find_first_of(Iter needles, size_t pos) const {
return find_first_of(const_range_type(needles), pos);
}
size_type find_first_of(Iter needles, size_t pos, size_t n) const {
return find_first_of(const_range_type(needles, n), pos);
}
size_type find_first_of(value_type c) const {
return find(c);
}
size_type find_first_of(value_type c, size_t pos) const {
return find(c, pos);
}
bool contains(const const_range_type& other) const {
return find(other) != std::string::npos;
}
bool contains(const value_type& other) const {
return find(other) != std::string::npos;
}
void swap(Range& rhs) {
std::swap(b_, rhs.b_);
std::swap(e_, rhs.e_);
}
bool startsWith(const const_range_type& other) const {
return size() >= other.size() &&
castToConst().subpiece(0, other.size()) == other;
}
bool startsWith(value_type c) const {
return !empty() && front() == c;
}
template <class Comp>
bool startsWith(const const_range_type& other, Comp&& eq) const {
if (size() < other.size()) {
return false;
}
auto const trunc = subpiece(0, other.size());
return std::equal(trunc.begin(),
trunc.end(),
other.begin(),
std::forward<Comp>(eq));
}
bool endsWith(const const_range_type& other) const {
return size() >= other.size() &&
castToConst().subpiece(size() - other.size()) == other;
}
bool endsWith(value_type c) const {
return !empty() && back() == c;
}
template <class Comp>
bool endsWith(const const_range_type& other, Comp&& eq) const {
if (size() < other.size()) {
return false;
}
auto const trunc = subpiece(size() - other.size());
return std::equal(trunc.begin(),
trunc.end(),
other.begin(),
std::forward<Comp>(eq));
}
template <class Comp>
bool equals(const const_range_type& other, Comp&& eq) const {
return size() == other.size() &&
std::equal(
begin(), end(), other.begin(), std::forward<Comp>(eq));
}
void erase(Iter b, Iter e) {
if (b == b_) {
b_ = e;
} else if (e == e_) {
e_ = b;
} else {
throw_exception<std::out_of_range>("index out of range");
}
}
bool removePrefix(const const_range_type& prefix) {
return startsWith(prefix) && (b_ += prefix.size(), true);
}
bool removePrefix(value_type prefix) {
return startsWith(prefix) && (++b_, true);
}
bool removeSuffix(const const_range_type& suffix) {
return endsWith(suffix) && (e_ -= suffix.size(), true);
}
bool removeSuffix(value_type suffix) {
return endsWith(suffix) && (--e_, true);
}
// # 924 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
bool replaceAt(size_t pos, const_range_type replacement) {
if (size() < pos + replacement.size()) {
return false;
}
std::copy(replacement.begin(), replacement.end(), begin() + pos);
return true;
}
// # 948 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
size_t replaceAll(const_range_type source, const_range_type dest) {
if (source.size() != dest.size()) {
throw_exception<std::invalid_argument>(
"replacement must have the same size as source");
}
if (dest.empty()) {
return 0;
}
size_t pos = 0;
size_t num_replaced = 0;
size_type found = std::string::npos;
while ((found = find(source, pos)) != std::string::npos) {
replaceAt(found, dest);
pos += source.size();
++num_replaced;
}
return num_replaced;
}
// # 1000 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
Range split_step(value_type delimiter) {
auto i = std::find(b_, e_, delimiter);
Range result(b_, i);
b_ = i == e_ ? e_ : std::next(i);
return result;
}
Range split_step(Range delimiter) {
auto i = find(delimiter);
Range result(b_, i == std::string::npos ? size() : i);
b_ = result.end() == e_
? e_
: std::next(result.end(),
typename std::iterator_traits<Iter>::
difference_type(delimiter.size()));
return result;
}
// # 1085 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
template <typename TProcess, typename... Args>
auto split_step(value_type delimiter, TProcess&& process, Args&&... args)
-> decltype(process(std::declval<Range>(),
std::forward<Args>(args)...)) {
return process(split_step(delimiter), std::forward<Args>(args)...);
}
template <typename TProcess, typename... Args>
auto split_step(Range delimiter, TProcess&& process, Args&&... args)
-> decltype(process(std::declval<Range>(),
std::forward<Args>(args)...)) {
return process(split_step(delimiter), std::forward<Args>(args)...);
}
private:
Iter b_, e_;
};
template <class Iter>
const typename Range<Iter>::size_type Range<Iter>::npos = std::string::npos;
template <class Iter>
void swap(Range<Iter>& lhs, Range<Iter>& rhs) {
lhs.swap(rhs);
}
template <class Iter>
constexpr Range<Iter> range(Iter first, Iter last) {
return Range<Iter>(first, last);
}
template <class Collection>
constexpr auto range(Collection& v) -> Range<decltype(v.data())> {
return Range<decltype(v.data())>(v.data(), v.data() + v.size());
}
template <class Collection>
constexpr auto range(Collection const& v) -> Range<decltype(v.data())> {
return Range<decltype(v.data())>(v.data(), v.data() + v.size());
}
template <class Collection>
constexpr auto crange(Collection const& v) -> Range<decltype(v.data())> {
return Range<decltype(v.data())>(v.data(), v.data() + v.size());
}
template <class T, size_t n>
constexpr Range<T*> range(T (&array)[n]) {
return Range<T*>(array, array + n);
}
template <class T, size_t n>
constexpr Range<T const*> range(T const (&array)[n]) {
return Range<T const*>(array, array + n);
}
template <class T, size_t n>
constexpr Range<T const*> crange(T const (&array)[n]) {
return Range<T const*>(array, array + n);
}
template <class T, size_t n>
constexpr Range<T*> range(std::array<T, n>& array) {
return Range<T*>{array};
}
template <class T, size_t n>
constexpr Range<T const*> range(std::array<T, n> const& array) {
return Range<T const*>{array};
}
template <class T, size_t n>
constexpr Range<T const*> crange(std::array<T, n> const& array) {
return Range<T const*>{array};
}
typedef Range<const char*> StringPiece;
typedef Range<char*> MutableStringPiece;
typedef Range<const unsigned char*> ByteRange;
typedef Range<unsigned char*> MutableByteRange;
template <class C>
std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os,
Range<C const*> piece) {
using StreamSize = decltype(os.width());
os.write(piece.start(), static_cast<StreamSize>(piece.size()));
return os;
}
template <class C>
std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os, Range<C*> piece) {
using StreamSize = decltype(os.width());
os.write(piece.start(), static_cast<StreamSize>(piece.size()));
return os;
}
template <class Iter>
inline bool operator==(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
}
template <class Iter>
inline bool operator!=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return !(operator==(lhs, rhs));
}
template <class Iter>
inline bool operator<(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return lhs.compare(rhs) < 0;
}
template <class Iter>
inline bool operator<=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return lhs.compare(rhs) <= 0;
}
template <class Iter>
inline bool operator>(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return lhs.compare(rhs) > 0;
}
template <class Iter>
inline bool operator>=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
return lhs.compare(rhs) >= 0;
}
namespace detail {
template <class A, class B>
struct ComparableAsStringPiece {
enum {
value = (std::is_convertible<A, StringPiece>::value &&
std::is_same<B, StringPiece>::value) ||
(std::is_convertible<B, StringPiece>::value &&
std::is_same<A, StringPiece>::value)
};
};
} // namespace detail
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator==(
const T& lhs, const U& rhs) {
return StringPiece(lhs) == StringPiece(rhs);
}
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator!=(
const T& lhs, const U& rhs) {
return StringPiece(lhs) != StringPiece(rhs);
}
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<(
const T& lhs, const U& rhs) {
return StringPiece(lhs) < StringPiece(rhs);
}
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>(
const T& lhs, const U& rhs) {
return StringPiece(lhs) > StringPiece(rhs);
}
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<=(
const T& lhs, const U& rhs) {
return StringPiece(lhs) <= StringPiece(rhs);
}
template <class T, class U>
std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>=(
const T& lhs, const U& rhs) {
return StringPiece(lhs) >= StringPiece(rhs);
}
template <class Iter, class Comp>
size_t qfind(const Range<Iter>& haystack, const Range<Iter>& needle, Comp eq) {
auto const nsize = needle.size();
if (haystack.size() < nsize) {
return std::string::npos;
}
if (!nsize) {
return 0;
}
auto const nsize_1 = nsize - 1;
auto const lastNeedle = needle[nsize_1];
std::string::size_type skip = 0;
auto i = haystack.begin();
auto iEnd = haystack.end() - nsize_1;
while (i < iEnd) {
while (!eq(i[nsize_1], lastNeedle)) {
if (++i == iEnd) {
return std::string::npos;
}
}
for (size_t j = 0;;) {
(static_cast<bool>(j < nsize)
? void(0)
: __assert_fail(
"j < nsize",
"tlm/deps/folly.exploded/include/folly/Range.h",
1329,
__extension__ __PRETTY_FUNCTION__));
if (!eq(i[j], needle[j])) {
if (skip == 0) {
skip = 1;
while (skip <= nsize_1 &&
!eq(needle[nsize_1 - skip], lastNeedle)) {
++skip;
}
}
i += skip;
break;
}
if (++j == nsize) {
return size_t(i - haystack.begin());
}
}
}
return std::string::npos;
}
namespace detail {
inline size_t qfind_first_byte_of(const StringPiece haystack,
const StringPiece needles) {
static auto const qfind_first_byte_of_fn =
folly::CpuId().sse42() ? qfind_first_byte_of_sse42
: qfind_first_byte_of_nosse;
return qfind_first_byte_of_fn(haystack, needles);
}
} // namespace detail
template <class Iter, class Comp>
size_t qfind_first_of(const Range<Iter>& haystack,
const Range<Iter>& needles,
Comp eq) {
auto ret = std::find_first_of(haystack.begin(),
haystack.end(),
needles.begin(),
needles.end(),
eq);
return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
}
struct AsciiCaseSensitive {
bool operator()(char lhs, char rhs) const {
return lhs == rhs;
}
};
struct AsciiCaseInsensitive {
bool operator()(char lhs, char rhs) const {
char k = lhs ^ rhs;
if (k == 0) {
return true;
}
if (k != 32) {
return false;
}
k = lhs | rhs;
return (k >= 'a' && k <= 'z');
}
};
template <class Iter>
size_t qfind(const Range<Iter>& haystack,
const typename Range<Iter>::value_type& needle) {
auto pos = std::find(haystack.begin(), haystack.end(), needle);
return pos == haystack.end() ? std::string::npos : pos - haystack.data();
}
template <class Iter>
size_t rfind(const Range<Iter>& haystack,
const typename Range<Iter>::value_type& needle) {
for (auto i = haystack.size(); i-- > 0;) {
if (haystack[i] == needle) {
return i;
}
}
return std::string::npos;
}
template <>
inline size_t qfind(const Range<const char*>& haystack, const char& needle) {
if (haystack.empty()) {
return std::string::npos;
}
auto pos = static_cast<const char*>(
::memchr(haystack.data(), needle, haystack.size()));
return pos == nullptr ? std::string::npos : pos - haystack.data();
}
template <>
inline size_t rfind(const Range<const char*>& haystack, const char& needle) {
if (haystack.empty()) {
return std::string::npos;
}
auto pos = static_cast<const char*>(
memrchr(haystack.data(), needle, haystack.size()));
return pos == nullptr ? std::string::npos : pos - haystack.data();
}
template <>
inline size_t qfind(const Range<const unsigned char*>& haystack,
const unsigned char& needle) {
if (haystack.empty()) {
return std::string::npos;
}
auto pos = static_cast<const unsigned char*>(
::memchr(haystack.data(), needle, haystack.size()));
return pos == nullptr ? std::string::npos : pos - haystack.data();
}
template <>
inline size_t rfind(const Range<const unsigned char*>& haystack,
const unsigned char& needle) {
if (haystack.empty()) {
return std::string::npos;
}
auto pos = static_cast<const unsigned char*>(
memrchr(haystack.data(), needle, haystack.size()));
return pos == nullptr ? std::string::npos : pos - haystack.data();
}
template <class Iter>
size_t qfind_first_of(const Range<Iter>& haystack, const Range<Iter>& needles) {
return qfind_first_of(haystack, needles, AsciiCaseSensitive());
}
template <>
inline size_t qfind_first_of(const Range<const char*>& haystack,
const Range<const char*>& needles) {
return detail::qfind_first_byte_of(haystack, needles);
}
template <>
inline size_t qfind_first_of(const Range<const unsigned char*>& haystack,
const Range<const unsigned char*>& needles) {
return detail::qfind_first_byte_of(StringPiece(haystack),
StringPiece(needles));
}
template <class Key, class Enable>
struct hasher;
template <class T>
struct hasher<folly::Range<T*>,
std::enable_if_t<std::is_integral<T>::value, void>> {
using folly_is_avalanching = std::true_type;
size_t operator()(folly::Range<T*> r) const {
return static_cast<size_t>(
hash::SpookyHashV2::Hash64(r.begin(), r.size() * sizeof(T), 0));
}
};
inline namespace literals {
inline namespace string_piece_literals {
constexpr Range<char const*> operator"" _sp(char const* str,
size_t len) noexcept {
return Range<char const*>(str, len);
}
// # 1536 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
constexpr Range<char16_t const*> operator"" _sp(char16_t const* str,
size_t len) noexcept {
return Range<char16_t const*>(str, len);
}
constexpr Range<char32_t const*> operator"" _sp(char32_t const* str,
size_t len) noexcept {
return Range<char32_t const*>(str, len);
}
constexpr Range<wchar_t const*> operator"" _sp(wchar_t const* str,
size_t len) noexcept {
return Range<wchar_t const*>(str, len);
}
} // namespace string_piece_literals
} // namespace literals
} // namespace folly
// # 1558 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
#pragma GCC diagnostic pop
// # 1558 "tlm/deps/folly.exploded/include/folly/Range.h" 3 4
namespace folly {
template <class T1>
struct IsRelocatable<folly::Range<T1>> : std::true_type {};
} // namespace folly
namespace ranges {
template <class T>
extern const bool enable_view;
template <class Iter>
inline constexpr bool enable_view<::folly::Range<Iter>> = true;
} // namespace ranges
// # 121 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/Pretty.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/Pretty.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/lang/CArray.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/lang/CArray.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/lang/CArray.h" 2 3 4
namespace folly {
template <typename V, size_t N>
struct c_array {
V data[N];
};
} // namespace folly
// # 24 "tlm/deps/folly.exploded/include/folly/lang/Pretty.h" 2 3 4
namespace folly {
namespace detail {
template <std::size_t S>
using pretty_carray = c_array<char, S>;
template <std::size_t S>
static constexpr pretty_carray<S> pretty_carray_from(char const (&in)[S]) {
pretty_carray<S> out{};
for (std::size_t i = 0; i < S; ++i) {
out.data[i] = in[i];
}
return out;
}
struct pretty_info {
std::size_t b;
std::size_t e;
};
template <typename To, std::size_t S>
static constexpr To pretty_info_to(pretty_info info, char const (&name)[S]) {
return To(name + info.b, info.e - info.b);
}
template <std::size_t S>
static constexpr std::size_t pretty_lfind(char const (&haystack)[S],
char const needle) {
for (std::size_t i = 0; i < S - 1; ++i) {
if (haystack[i] == needle) {
return i;
}
}
return ~std::size_t(0);
}
template <std::size_t S>
static constexpr std::size_t pretty_rfind(char const (&haystack)[S],
char const needle) {
for (std::size_t i = S; i != 0; --i) {
if (haystack[i - 1] == needle) {
return i - 1;
}
}
return ~std::size_t(0);
}
struct pretty_tag_msc {};
struct pretty_tag_gcc {};
using pretty_default_tag = std::
conditional_t<kMscVer && !kIsClang, pretty_tag_msc, pretty_tag_gcc>;
template <typename T>
static constexpr auto pretty_raw(pretty_tag_msc) {
}
template <typename T>
static constexpr auto pretty_raw(pretty_tag_gcc) {
return pretty_carray_from(__PRETTY_FUNCTION__);
}
template <std::size_t S>
static constexpr pretty_info pretty_parse(pretty_tag_msc,
char const (&name)[S]) {
auto const la = pretty_lfind(name, '<');
auto const rp = pretty_rfind(name, '>');
return pretty_info{la + 1, rp};
}
template <std::size_t S>
static constexpr pretty_info pretty_parse(pretty_tag_gcc,
char const (&name)[S]) {
auto const eq = pretty_lfind(name, '=');
auto const br = pretty_rfind(name, ']');
return pretty_info{eq + 2, br};
}
template <typename T, typename Tag>
struct pretty_name_zarray {
static constexpr auto raw_() {
constexpr auto const raw_ = pretty_raw<T>(Tag{});
return raw_;
}
static constexpr auto raw = raw_();
static constexpr auto info = pretty_parse(Tag{}, raw.data);
static constexpr auto size = info.e - info.b;
static constexpr auto zarray_() {
pretty_carray<size + 1> data{};
for (std::size_t i = 0; i < size; ++i) {
data.data[i] = raw.data[info.b + i];
}
data.data[size] = 0;
return data;
}
static constexpr pretty_carray<size + 1> zarray = zarray_();
};
template <typename T, typename Tag>
constexpr pretty_carray<pretty_name_zarray<T, Tag>::size + 1>
pretty_name_zarray<T, Tag>::zarray;
} // namespace detail
// # 153 "tlm/deps/folly.exploded/include/folly/lang/Pretty.h" 3 4
template <typename T>
constexpr char const* pretty_name() {
return detail::pretty_name_zarray<T, detail::pretty_default_tag>::zarray
.data;
}
} // namespace folly
// # 126 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/portability/Math.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/portability/Math.h" 3 4
// # 20 "tlm/deps/folly.exploded/include/folly/portability/Math.h" 2 3 4
namespace folly {
using std::nextafter;
using std::remainder;
// # 90 "tlm/deps/folly.exploded/include/folly/portability/Math.h" 3 4
} // namespace folly
// # 127 "tlm/deps/folly.exploded/include/folly/Conv.h" 2 3 4
namespace folly {
enum class ConversionCode : unsigned char {
SUCCESS,
EMPTY_INPUT_STRING,
NO_DIGITS,
BOOL_OVERFLOW,
BOOL_INVALID_VALUE,
NON_DIGIT_CHAR,
INVALID_LEADING_CHAR,
POSITIVE_OVERFLOW,
NEGATIVE_OVERFLOW,
STRING_TO_FLOAT_ERROR,
NON_WHITESPACE_AFTER_END,
ARITH_POSITIVE_OVERFLOW,
ARITH_NEGATIVE_OVERFLOW,
ARITH_LOSS_OF_PRECISION,
NUM_ERROR_CODES,
};
struct ConversionErrorBase : std::range_error {
using std::range_error::range_error;
};
class ConversionError : public ConversionErrorBase {
public:
ConversionError(const std::string& str, ConversionCode code)
: ConversionErrorBase(str), code_(code) {
}
ConversionError(const char* str, ConversionCode code)
: ConversionErrorBase(str), code_(code) {
}
ConversionCode errorCode() const {
return code_;
}
private:
ConversionCode code_;
};
// # 190 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
ConversionError makeConversionError(ConversionCode code, StringPiece input);
namespace detail {
inline ConversionCode enforceWhitespaceErr(StringPiece sp) {
for (auto c : sp) {
if ((__builtin_expect((!std::isspace(c)), 0))) {
return ConversionCode::NON_WHITESPACE_AFTER_END;
}
}
return ConversionCode::SUCCESS;
}
inline void enforceWhitespace(StringPiece sp) {
auto err = enforceWhitespaceErr(sp);
if (err != ConversionCode::SUCCESS) {
throw_exception(makeConversionError(err, sp));
}
}
} // namespace detail
template <class Tgt, class Src>
typename std::enable_if<
std::is_same<Tgt, typename std::decay<Src>::type>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(Src&& value) {
return std::forward<Src>(value);
}
template <class Tgt, class Src>
typename std::enable_if<
std::is_same<Tgt, typename std::decay<Src>::type>::value,
Tgt>::type
to(Src&& value) {
return std::forward<Src>(value);
}
// # 245 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class Tgt, class Src>
typename std::enable_if<std::is_arithmetic<Src>::value &&
!std::is_same<Tgt, Src>::value &&
std::is_same<Tgt, bool>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) {
return value != Src();
}
template <class Tgt, class Src>
typename std::enable_if<std::is_arithmetic<Src>::value &&
!std::is_same<Tgt, Src>::value &&
std::is_same<Tgt, bool>::value,
Tgt>::type
to(const Src& value) {
return value != Src();
}
namespace detail {
// # 296 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <typename... Ts>
struct LastElementImpl {
static void call(Ignored<Ts>...) {
}
};
template <typename Head, typename... Ts>
struct LastElementImpl<Head, Ts...> {
template <typename Last>
static Last call(Ignored<Ts>..., Last&& last) {
return std::forward<Last>(last);
}
};
template <typename... Ts>
auto getLastElement(const Ts&... ts)
-> decltype(LastElementImpl<Ts...>::call(ts...)) {
return LastElementImpl<Ts...>::call(ts...);
}
template <class... Ts>
struct LastElement : std::decay<decltype(LastElementImpl<Ts...>::call(
std::declval<Ts>()...))> {};
} // namespace detail
namespace detail {
template <typename IntegerType>
constexpr unsigned int digitsEnough() {
auto const digits10 = std::numeric_limits<IntegerType>::digits10;
return static_cast<unsigned int>(digits10) + 1;
}
inline size_t unsafeTelescope128(char* buffer,
size_t room,
unsigned __int128 x) {
typedef unsigned __int128 Usrc;
size_t p = room - 1;
while (x >= (Usrc(1) << 64)) {
const auto y = x / 10;
const auto digit = x % 10;
buffer[p--] = static_cast<char>('0' + digit);
x = y;
}
uint64_t xx = static_cast<uint64_t>(x);
while (xx >= 10) {
const auto y = xx / 10ULL;
const auto digit = xx % 10ULL;
buffer[p--] = static_cast<char>('0' + digit);
xx = y;
}
buffer[p] = static_cast<char>('0' + xx);
return p;
}
} // namespace detail
// # 378 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
inline uint32_t digits10(uint64_t v) {
// # 388 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
alignas(64) static const uint64_t powersOf10[20] = {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
100000000000000000,
1000000000000000000,
10000000000000000000UL,
};
if ((__builtin_expect((!v), 0))) {
return 1;
}
const uint32_t leadingZeroes = __builtin_clzll(v);
const auto bits = 63 - leadingZeroes;
const uint32_t minLength = 1 + ((bits * 77) >> 8);
return minLength + uint32_t(v >= powersOf10[minLength]);
// # 451 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
}
// # 466 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
inline uint32_t uint64ToBufferUnsafe(uint64_t v, char* const buffer) {
auto const result = digits10(v);
uint32_t pos = result - 1;
while (v >= 10) {
auto const q = v / 10;
auto const r = v % 10;
buffer[pos--] = static_cast<char>('0' + r);
v = q;
}
buffer[pos] = static_cast<char>(v + '0');
return result;
}
template <class Tgt>
void toAppend(char value, Tgt* result) {
*result += value;
}
template <class T>
constexpr typename std::enable_if<std::is_same<T, char>::value, size_t>::type
estimateSpaceNeeded(T) {
return 1;
}
template <size_t N>
constexpr size_t estimateSpaceNeeded(const char (&)[N]) {
return N;
}
template <class Tgt, class Src>
typename std::enable_if<std::is_convertible<Src, const char*>::value &&
IsSomeString<Tgt>::value>::type
toAppend(Src value, Tgt* result) {
const char* c = value;
if (c) {
result->append(value);
}
}
template <class Src>
typename std::enable_if<std::is_convertible<Src, const char*>::value,
size_t>::type
estimateSpaceNeeded(Src value) {
const char* c = value;
if (c) {
return folly::StringPiece(value).size();
};
return 0;
}
template <class Src>
typename std::enable_if<IsSomeString<Src>::value, size_t>::type
estimateSpaceNeeded(Src const& value) {
return value.size();
}
template <class Src>
typename std::enable_if<std::is_convertible<Src, folly::StringPiece>::value &&
!IsSomeString<Src>::value &&
!std::is_convertible<Src, const char*>::value,
size_t>::type
estimateSpaceNeeded(Src value) {
return folly::StringPiece(value).size();
}
template <>
inline size_t estimateSpaceNeeded(std::nullptr_t) {
return 0;
}
template <class Src>
typename std::enable_if<std::is_pointer<Src>::value &&
IsSomeString<std::remove_pointer<Src>>::value,
size_t>::type
estimateSpaceNeeded(Src value) {
return value->size();
}
template <class Tgt, class Src>
typename std::enable_if<IsSomeString<Src>::value &&
IsSomeString<Tgt>::value>::type
toAppend(const Src& value, Tgt* result) {
result->append(value);
}
template <class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
StringPiece value, Tgt* result) {
result->append(value.data(), value.size());
}
template <class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
const fbstring& value, Tgt* result) {
result->append(value.data(), value.size());
}
template <class Tgt>
void toAppend(__int128 value, Tgt* result) {
typedef unsigned __int128 Usrc;
char buffer[detail::digitsEnough<unsigned __int128>() + 1];
size_t p;
if (value < 0) {
p = detail::unsafeTelescope128(buffer, sizeof(buffer), -Usrc(value));
buffer[--p] = '-';
} else {
p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
}
result->append(buffer + p, buffer + sizeof(buffer));
}
template <class Tgt>
void toAppend(unsigned __int128 value, Tgt* result) {
char buffer[detail::digitsEnough<unsigned __int128>()];
size_t p;
p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
result->append(buffer + p, buffer + sizeof(buffer));
}
template <class T>
constexpr
typename std::enable_if<std::is_same<T, __int128>::value, size_t>::type
estimateSpaceNeeded(T) {
return detail::digitsEnough<__int128>();
}
template <class T>
constexpr typename std::enable_if<std::is_same<T, unsigned __int128>::value,
size_t>::type
estimateSpaceNeeded(T) {
return detail::digitsEnough<unsigned __int128>();
}
// # 647 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class Tgt, class Src>
typename std::enable_if<std::is_integral<Src>::value &&
std::is_signed<Src>::value &&
IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
toAppend(Src value, Tgt* result) {
char buffer[20];
if (value < 0) {
result->push_back('-');
result->append(buffer,
uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1,
buffer));
} else {
result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
}
}
template <class Src>
typename std::enable_if<std::is_integral<Src>::value &&
std::is_signed<Src>::value &&
sizeof(Src) >= 4 && sizeof(Src) < 16,
size_t>::type
estimateSpaceNeeded(Src value) {
if (value < 0) {
return 1 + digits10(~static_cast<uint64_t>(value) + 1);
}
return digits10(static_cast<uint64_t>(value));
}
template <class Tgt, class Src>
typename std::enable_if<std::is_integral<Src>::value &&
!std::is_signed<Src>::value &&
IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
toAppend(Src value, Tgt* result) {
char buffer[20];
result->append(buffer, uint64ToBufferUnsafe(value, buffer));
}
template <class Src>
typename std::enable_if<std::is_integral<Src>::value &&
!std::is_signed<Src>::value &&
sizeof(Src) >= 4 && sizeof(Src) < 16,
size_t>::type
estimateSpaceNeeded(Src value) {
return digits10(value);
}
template <class Tgt, class Src>
typename std::enable_if<std::is_integral<Src>::value &&
IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
toAppend(Src value, Tgt* result) {
typedef typename std::conditional<std::is_signed<Src>::value,
int64_t,
uint64_t>::type Intermediate;
toAppend<Tgt>(static_cast<Intermediate>(value), result);
}
template <class Src>
typename std::enable_if<std::is_integral<Src>::value && sizeof(Src) < 4 &&
!std::is_same<Src, char>::value,
size_t>::type
estimateSpaceNeeded(Src value) {
typedef typename std::conditional<std::is_signed<Src>::value,
int64_t,
uint64_t>::type Intermediate;
return estimateSpaceNeeded(static_cast<Intermediate>(value));
}
template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Src>::value &&
IsSomeString<Tgt>::value>::type
toAppend(Src value, Tgt* result) {
toAppend(to_underlying(value), result);
}
template <class Src>
typename std::enable_if<std::is_enum<Src>::value, size_t>::type
estimateSpaceNeeded(Src value) {
return estimateSpaceNeeded(to_underlying(value));
}
namespace detail {
constexpr int kConvMaxDecimalInShortestLow = -6;
constexpr int kConvMaxDecimalInShortestHigh = 21;
} // namespace detail
template <class Tgt, class Src>
typename std::enable_if<std::is_floating_point<Src>::value &&
IsSomeString<Tgt>::value>::type
toAppend(Src value,
Tgt* result,
double_conversion::DoubleToStringConverter::DtoaMode mode,
unsigned int numDigits) {
using namespace double_conversion;
DoubleToStringConverter conv(DoubleToStringConverter::NO_FLAGS,
"Infinity",
"NaN",
'E',
detail::kConvMaxDecimalInShortestLow,
detail::kConvMaxDecimalInShortestHigh,
6,
1);
char buffer[256];
StringBuilder builder(buffer, sizeof(buffer));
switch (mode) {
case DoubleToStringConverter::SHORTEST:
conv.ToShortest(value, &builder);
break;
case DoubleToStringConverter::SHORTEST_SINGLE:
conv.ToShortestSingle(static_cast<float>(value), &builder);
break;
case DoubleToStringConverter::FIXED:
conv.ToFixed(value, int(numDigits), &builder);
break;
case DoubleToStringConverter::PRECISION:
default:
(static_cast<bool>(mode == DoubleToStringConverter::PRECISION)
? void(0)
: __assert_fail("mode == DoubleToStringConverter::PRECISION",
"tlm/deps/folly.exploded/include/folly/Conv.h",
785,
__extension__ __PRETTY_FUNCTION__));
conv.ToPrecision(value, int(numDigits), &builder);
break;
}
const size_t length = size_t(builder.position());
builder.Finalize();
result->append(buffer, length);
}
template <class Tgt, class Src>
typename std::enable_if<std::is_floating_point<Src>::value &&
IsSomeString<Tgt>::value>::type
toAppend(Src value, Tgt* result) {
toAppend(value,
result,
double_conversion::DoubleToStringConverter::SHORTEST,
0);
}
template <class Src>
typename std::enable_if<std::is_floating_point<Src>::value, size_t>::type
estimateSpaceNeeded(Src value) {
constexpr int kMaxMantissaSpace =
double_conversion::DoubleToStringConverter::kBase10MaximalLength +
1;
constexpr int kMaxExponentSpace = 2 + 3;
static const int kMaxPositiveSpace = std::max({
kMaxMantissaSpace + kMaxExponentSpace,
kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
detail::kConvMaxDecimalInShortestHigh,
});
return size_t(kMaxPositiveSpace + (value < 0 ? 1 : 0));
}
template <class Src>
struct HasLengthEstimator : std::false_type {};
template <class Src>
constexpr typename std::enable_if<
!std::is_fundamental<Src>::value &&
!std::is_same<__int128, Src>::value &&
!std::is_same<unsigned __int128, Src>::value &&
!IsSomeString<Src>::value &&
!std::is_convertible<Src, const char*>::value &&
!std::is_convertible<Src, StringPiece>::value &&
!std::is_enum<Src>::value && !HasLengthEstimator<Src>::value,
size_t>::type
estimateSpaceNeeded(const Src&) {
return sizeof(Src) + 1;
}
namespace detail {
template <class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
estimateSpaceToReserve(size_t sofar, Tgt*) {
return sofar;
}
template <class T, class... Ts>
size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
}
template <class... Ts>
void reserveInTarget(const Ts&... vs) {
getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
}
template <class Delimiter, class... Ts>
void reserveInTargetDelim(const Delimiter& d, const Ts&... vs) {
static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
size_t fordelim =
(sizeof...(vs) - 2) *
estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
}
template <class T, class Tgt>
typename std::enable_if<
IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
toAppendStrImpl(const T& v, Tgt result) {
toAppend(v, result);
}
template <class T, class... Ts>
typename std::enable_if<
sizeof...(Ts) >= 2 &&
IsSomeString<typename std::remove_pointer<typename detail::LastElement<
const Ts&...>::type>::type>::value>::type
toAppendStrImpl(const T& v, const Ts&... vs) {
toAppend(v, getLastElement(vs...));
toAppendStrImpl(vs...);
}
template <class Delimiter, class T, class Tgt>
typename std::enable_if<
IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
toAppendDelimStrImpl(const Delimiter&, const T& v, Tgt result) {
toAppend(v, result);
}
template <class Delimiter, class T, class... Ts>
typename std::enable_if<
sizeof...(Ts) >= 2 &&
IsSomeString<typename std::remove_pointer<typename detail::LastElement<
const Ts&...>::type>::type>::value>::type
toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
toAppend(v, detail::getLastElement(vs...));
toAppend(delim, detail::getLastElement(vs...));
toAppendDelimStrImpl(delim, vs...);
}
} // namespace detail
// # 948 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class... Ts>
typename std::enable_if<
sizeof...(Ts) >= 3 &&
IsSomeString<typename std::remove_pointer<typename detail::LastElement<
const Ts&...>::type>::type>::value>::type
toAppend(const Ts&... vs) {
::folly::detail::toAppendStrImpl(vs...);
}
// # 977 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class... Ts>
typename std::enable_if<IsSomeString<typename std::remove_pointer<
typename detail::LastElement<const Ts&...>::type>::type>::value>::type
toAppendFit(const Ts&... vs) {
::folly::detail::reserveInTarget(vs...);
toAppend(vs...);
}
template <class Ts>
void toAppendFit(const Ts&) {
}
template <class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(Tgt*) {
}
template <class Delimiter, class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
const Delimiter&, Tgt*) {
}
template <class Delimiter, class T, class Tgt>
typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
const Delimiter&, const T& v, Tgt* tgt) {
toAppend(v, tgt);
}
template <class Delimiter, class... Ts>
typename std::enable_if<
sizeof...(Ts) >= 3 &&
IsSomeString<typename std::remove_pointer<typename detail::LastElement<
const Ts&...>::type>::type>::value>::type
toAppendDelim(const Delimiter& delim, const Ts&... vs) {
detail::toAppendDelimStrImpl(delim, vs...);
}
template <class Delimiter, class... Ts>
typename std::enable_if<IsSomeString<typename std::remove_pointer<
typename detail::LastElement<const Ts&...>::type>::type>::value>::type
toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
detail::reserveInTargetDelim(delim, vs...);
toAppendDelim(delim, vs...);
}
template <class De, class Ts>
void toAppendDelimFit(const De&, const Ts&) {
}
template <class Tgt, class... Ts>
typename std::enable_if<
IsSomeString<Tgt>::value &&
(sizeof...(Ts) != 1 ||
!std::is_same<Tgt,
typename detail::LastElement<
const Ts&...>::type>::value),
Tgt>::type
to(const Ts&... vs) {
Tgt result;
toAppendFit(vs..., &result);
return result;
}
// # 1067 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class Tgt, class Src>
typename std::enable_if<IsSomeString<Tgt>::value &&
std::is_floating_point<Src>::value,
Tgt>::type
to(Src value) {
Tgt result;
toAppend(value, &result);
return result;
}
template <class Tgt, class Delim, class Src>
typename std::enable_if<
IsSomeString<Tgt>::value &&
std::is_same<Tgt, typename std::decay<Src>::type>::value,
Tgt>::type
toDelim(const Delim&, Src&& value) {
return std::forward<Src>(value);
}
template <class Tgt, class Delim, class... Ts>
typename std::enable_if<
IsSomeString<Tgt>::value &&
(sizeof...(Ts) != 1 ||
!std::is_same<Tgt,
typename detail::LastElement<
const Ts&...>::type>::value),
Tgt>::type
toDelim(const Delim& delim, const Ts&... vs) {
Tgt result;
toAppendDelimFit(delim, vs..., &result);
return result;
}
namespace detail {
Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
template <typename T>
Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
extern template Expected<float, ConversionCode> str_to_floating<float>(
StringPiece* src) noexcept;
extern template Expected<double, ConversionCode> str_to_floating<double>(
StringPiece* src) noexcept;
template <class Tgt>
Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
extern template Expected<char, ConversionCode> digits_to<char>(
const char*, const char*) noexcept;
extern template Expected<signed char, ConversionCode> digits_to<signed char>(
const char*, const char*) noexcept;
extern template Expected<unsigned char, ConversionCode>
digits_to<unsigned char>(const char*, const char*) noexcept;
extern template Expected<short, ConversionCode> digits_to<short>(
const char*, const char*) noexcept;
extern template Expected<unsigned short, ConversionCode>
digits_to<unsigned short>(const char*, const char*) noexcept;
extern template Expected<int, ConversionCode> digits_to<int>(
const char*, const char*) noexcept;
extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
const char*, const char*) noexcept;
extern template Expected<long, ConversionCode> digits_to<long>(
const char*, const char*) noexcept;
extern template Expected<unsigned long, ConversionCode>
digits_to<unsigned long>(const char*, const char*) noexcept;
extern template Expected<long long, ConversionCode> digits_to<long long>(
const char*, const char*) noexcept;
extern template Expected<unsigned long long, ConversionCode>
digits_to<unsigned long long>(const char*, const char*) noexcept;
extern template Expected<__int128, ConversionCode> digits_to<__int128>(
const char*, const char*) noexcept;
extern template Expected<unsigned __int128, ConversionCode>
digits_to<unsigned __int128>(const char*, const char*) noexcept;
template <class T>
Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
extern template Expected<char, ConversionCode> str_to_integral<char>(
StringPiece* src) noexcept;
extern template Expected<signed char, ConversionCode>
str_to_integral<signed char>(StringPiece* src) noexcept;
extern template Expected<unsigned char, ConversionCode>
str_to_integral<unsigned char>(StringPiece* src) noexcept;
extern template Expected<short, ConversionCode> str_to_integral<short>(
StringPiece* src) noexcept;
extern template Expected<unsigned short, ConversionCode>
str_to_integral<unsigned short>(StringPiece* src) noexcept;
extern template Expected<int, ConversionCode> str_to_integral<int>(
StringPiece* src) noexcept;
extern template Expected<unsigned int, ConversionCode>
str_to_integral<unsigned int>(StringPiece* src) noexcept;
extern template Expected<long, ConversionCode> str_to_integral<long>(
StringPiece* src) noexcept;
extern template Expected<unsigned long, ConversionCode>
str_to_integral<unsigned long>(StringPiece* src) noexcept;
extern template Expected<long long, ConversionCode> str_to_integral<long long>(
StringPiece* src) noexcept;
extern template Expected<unsigned long long, ConversionCode>
str_to_integral<unsigned long long>(StringPiece* src) noexcept;
extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
StringPiece* src) noexcept;
extern template Expected<unsigned __int128, ConversionCode>
str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
template <typename T>
typename std::enable_if<std::is_same<T, bool>::value,
Expected<T, ConversionCode>>::type
convertTo(StringPiece* src) noexcept {
return str_to_bool(src);
}
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value,
Expected<T, ConversionCode>>::type
convertTo(StringPiece* src) noexcept {
return str_to_floating<T>(src);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value &&
!std::is_same<T, bool>::value,
Expected<T, ConversionCode>>::type
convertTo(StringPiece* src) noexcept {
return str_to_integral<T>(src);
}
} // namespace detail
template <typename Tgt>
typename std::enable_if<std::is_integral<Tgt>::value &&
!std::is_same<Tgt, bool>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const char* b, const char* e) {
return detail::digits_to<Tgt>(b, e);
}
template <typename Tgt>
typename std::enable_if<std::is_integral<Tgt>::value &&
!std::is_same<Tgt, bool>::value,
Tgt>::type
to(const char* b, const char* e) {
return tryTo<Tgt>(b, e).thenOrThrow([](Tgt res) { return res; },
[=](ConversionCode code) {
return makeConversionError(
code, StringPiece(b, e));
});
}
// # 1260 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <typename Tgt>
[[nodiscard]] inline
typename std::enable_if<std::is_arithmetic<Tgt>::value,
Expected<StringPiece, ConversionCode>>::type
parseTo(StringPiece src, Tgt& out) {
return detail::convertTo<Tgt>(&src).then(
[&](Tgt res) { return void(out = res), src; });
}
namespace detail {
template <class Tgt>
typename std::enable_if<!std::is_same<Tgt, bool>::value &&
(std::is_integral<Tgt>::value ||
std::is_floating_point<Tgt>::value),
Expected<Tgt, ConversionCode>>::type
convertTo(const bool& value) noexcept {
return static_cast<Tgt>(value ? 1 : 0);
}
template <class Tgt, class Src>
typename std::enable_if<
std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
!std::is_same<Tgt, bool>::value && std::is_integral<Tgt>::value,
Expected<Tgt, ConversionCode>>::type
convertTo(const Src& value) noexcept {
if (std::make_unsigned_t<Tgt>(std::numeric_limits<Tgt>::max()) <
std::make_unsigned_t<Src>(std::numeric_limits<Src>::max())) {
if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
}
}
if (std::is_signed<Src>::value &&
(!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
}
}
return static_cast<Tgt>(value);
}
template <class Tgt, class Src>
typename std::enable_if<std::is_floating_point<Tgt>::value &&
std::is_floating_point<Src>::value &&
!std::is_same<Tgt, Src>::value,
Expected<Tgt, ConversionCode>>::type
convertTo(const Src& value) noexcept {
if (std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
if (value > std::numeric_limits<Tgt>::max()) {
return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
}
if (value < std::numeric_limits<Tgt>::lowest()) {
return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
}
}
return static_cast<Tgt>(value);
}
template <typename Tgt, typename Src>
inline typename std::enable_if<std::is_floating_point<Src>::value &&
std::is_integral<Tgt>::value &&
!std::is_same<Tgt, bool>::value,
bool>::type
checkConversion(const Src& value) {
constexpr Src tgtMaxAsSrc =
static_cast<Src>(std::numeric_limits<Tgt>::max());
constexpr Src tgtMinAsSrc =
static_cast<Src>(std::numeric_limits<Tgt>::min());
if (value >= tgtMaxAsSrc) {
if (value > tgtMaxAsSrc) {
return false;
}
const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
if (static_cast<Tgt>(value - mmax) >
std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
return false;
}
} else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
if (value < tgtMinAsSrc) {
return false;
}
const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
if (static_cast<Tgt>(value - mmin) <
std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
return false;
}
}
return true;
}
template <typename Tgt, typename Src>
constexpr typename std::enable_if<std::is_integral<Src>::value &&
std::is_floating_point<Tgt>::value,
bool>::type
checkConversion(const Src&) {
return true;
}
template <typename Tgt, typename Src>
constexpr typename std::enable_if<std::is_floating_point<Src>::value &&
std::is_same<Tgt, bool>::value,
bool>::type
checkConversion(const Src&) {
return true;
}
// # 1400 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <typename Tgt, typename Src>
typename std::enable_if<(std::is_integral<Src>::value &&
std::is_floating_point<Tgt>::value) ||
(std::is_floating_point<Src>::value &&
std::is_integral<Tgt>::value),
Expected<Tgt, ConversionCode>>::type
convertTo(const Src& value) noexcept {
if ((__builtin_expect((checkConversion<Tgt>(value)), 1))) {
Tgt result = static_cast<Tgt>(value);
if ((__builtin_expect((checkConversion<Src>(result)), 1))) {
Src witness = static_cast<Src>(result);
if ((__builtin_expect((value == witness), 1))) {
return result;
}
}
}
return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
}
template <typename Tgt, typename Src>
inline std::string errorValue(const Src& value) {
return to<std::string>("(", pretty_name<Tgt>(), ") ", value);
}
template <typename Tgt, typename Src>
using IsArithToArith = bool_constant<
!std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
std::is_arithmetic<Src>::value && std::is_arithmetic<Tgt>::value>;
} // namespace detail
template <typename Tgt, typename Src>
typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) noexcept {
return detail::convertTo<Tgt>(value);
}
template <typename Tgt, typename Src>
typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
const Src& value) {
return tryTo<Tgt>(value).thenOrThrow(
[](Tgt res) { return res; },
[&](ConversionCode e) {
return makeConversionError(e, detail::errorValue<Tgt>(value));
});
}
// # 1460 "tlm/deps/folly.exploded/include/folly/Conv.h" 3 4
template <class T>
[[nodiscard]]
typename std::enable_if<std::is_enum<T>::value,
Expected<StringPiece, ConversionCode>>::type
parseTo(StringPiece in, T& out) noexcept {
typename std::underlying_type<T>::type tmp{};
auto restOrError = parseTo(in, tmp);
out = static_cast<T>(tmp);
return restOrError;
}
[[nodiscard]] inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in, StringPiece& out) noexcept {
out = in;
return StringPiece{in.end(), in.end()};
}
[[nodiscard]] inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in, std::string& out) {
out.clear();
out.append(in.data(), in.size());
return StringPiece{in.end(), in.end()};
}
[[nodiscard]] inline Expected<StringPiece, ConversionCode> parseTo(
StringPiece in, fbstring& out) {
out.clear();
out.append(in.data(), in.size());
return StringPiece{in.end(), in.end()};
}
namespace detail {
template <typename Tgt>
using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
struct CheckTrailingSpace {
Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
auto e = enforceWhitespaceErr(sp);
if ((__builtin_expect((e != ConversionCode::SUCCESS), 0))) {
return makeUnexpected(e);
}
return unit;
}
};
template <class Error>
struct ReturnUnit {
template <class T>
constexpr Expected<Unit, Error> operator()(T&&) const {
return unit;
}
};
template <class Tgt>
inline typename std::enable_if<std::is_void<ParseToResult<Tgt>>::value,
Expected<StringPiece, ConversionCode>>::type
parseToWrap(StringPiece sp, Tgt& out) {
parseTo(sp, out);
return StringPiece(sp.end(), sp.end());
}
template <class Tgt>
inline typename std::enable_if<!std::is_void<ParseToResult<Tgt>>::value,
ParseToResult<Tgt>>::type
parseToWrap(StringPiece sp, Tgt& out) {
return parseTo(sp, out);
}
template <typename Tgt>
using ParseToError = ExpectedErrorType<decltype(
detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
} // namespace detail
template <class Tgt>
inline typename std::enable_if<!std::is_same<StringPiece, Tgt>::value,
Expected<Tgt, detail::ParseToError<Tgt>>>::type
tryTo(StringPiece src) {
Tgt result{};
using Error = detail::ParseToError<Tgt>;
using Check = typename std::conditional<std::is_arithmetic<Tgt>::value,
detail::CheckTrailingSpace,
detail::ReturnUnit<Error>>::type;
return parseTo(src, result).then(Check(), [&](Unit) {
return std::move(result);
});
}
template <class Tgt, class Src>
inline typename std::enable_if<IsSomeString<Src>::value &&
!std::is_same<StringPiece, Tgt>::value,
Tgt>::type
to(Src const& src) {
return to<Tgt>(StringPiece(src.data(), src.size()));
}
template <class Tgt>
inline typename std::enable_if<!std::is_same<StringPiece, Tgt>::value,
Tgt>::type
to(StringPiece src) {
Tgt result{};
using Error = detail::ParseToError<Tgt>;
using Check = typename std::conditional<std::is_arithmetic<Tgt>::value,
detail::CheckTrailingSpace,
detail::ReturnUnit<Error>>::type;
auto tmp = detail::parseToWrap(src, result);
return tmp
.thenOrThrow(Check(),
[&](Error e) {
throw_exception(makeConversionError(e, src));
})
.thenOrThrow(
[&](Unit) { return std::move(result); },
[&](Error e) {
throw_exception(makeConversionError(e, tmp.value()));
});
}
template <class Tgt>
Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
Tgt result;
return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
*src = sp;
return std::move(result);
});
}
template <class Tgt>
Tgt to(StringPiece* src) {
Tgt result{};
using Error = detail::ParseToError<Tgt>;
return parseTo(*src, result)
.thenOrThrow(
[&, src](StringPiece sp) -> Tgt {
*src = sp;
return std::move(result);
},
[=](Error e) { return makeConversionError(e, *src); });
}
template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Src>::value &&
!std::is_same<Src, Tgt>::value &&
!std::is_convertible<Tgt, StringPiece>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) {
return tryTo<Tgt>(to_underlying(value));
}
template <class Tgt, class Src>
typename std::enable_if<!std::is_convertible<Src, StringPiece>::value &&
std::is_enum<Tgt>::value &&
!std::is_same<Src, Tgt>::value,
Expected<Tgt, ConversionCode>>::type
tryTo(const Src& value) {
using I = typename std::underlying_type<Tgt>::type;
return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
}
template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Src>::value &&
!std::is_same<Src, Tgt>::value &&
!std::is_convertible<Tgt, StringPiece>::value,
Tgt>::type
to(const Src& value) {
return to<Tgt>(to_underlying(value));
}
template <class Tgt, class Src>
typename std::enable_if<!std::is_convertible<Src, StringPiece>::value &&
std::is_enum<Tgt>::value &&
!std::is_same<Src, Tgt>::value,
Tgt>::type
to(const Src& value) {
return static_cast<Tgt>(
to<typename std::underlying_type<Tgt>::type>(value));
}
} // namespace folly
// # 26 "tlm/deps/folly.exploded/include/folly/Exception.h" 2 3 4
namespace folly {
inline std::system_error makeSystemErrorExplicit(int err, const char* msg) {
return std::system_error(err, std::system_category(), msg);
}
template <class... Args>
std::system_error makeSystemErrorExplicit(int err, Args&&... args) {
return makeSystemErrorExplicit(
err, to<fbstring>(std::forward<Args>(args)...).c_str());
}
inline std::system_error makeSystemError(const char* msg) {
return makeSystemErrorExplicit((*__errno_location()), msg);
}
template <class... Args>
std::system_error makeSystemError(Args&&... args) {
return makeSystemErrorExplicit((*__errno_location()),
std::forward<Args>(args)...);
}
[[noreturn]] inline void throwSystemErrorExplicit(int err, const char* msg) {
throw_exception(makeSystemErrorExplicit(err, msg));
}
template <class... Args>
[[noreturn]] void throwSystemErrorExplicit(int err, Args&&... args) {
throw_exception(makeSystemErrorExplicit(err, std::forward<Args>(args)...));
}
template <class... Args>
[[noreturn]] void throwSystemError(Args&&... args) {
throwSystemErrorExplicit((*__errno_location()),
std::forward<Args>(args)...);
}
template <class... Args>
void checkPosixError(int err, Args&&... args) {
if ((__builtin_expect((err != 0), 0))) {
throwSystemErrorExplicit(err, std::forward<Args>(args)...);
}
}
template <class... Args>
void checkKernelError(ssize_t ret, Args&&... args) {
if ((__builtin_expect((ret < 0), 0))) {
throwSystemErrorExplicit(int(-ret), std::forward<Args>(args)...);
}
}
template <class... Args>
void checkUnixError(ssize_t ret, Args&&... args) {
if ((__builtin_expect((ret == -1), 0))) {
throwSystemError(std::forward<Args>(args)...);
}
}
template <class... Args>
void checkUnixErrorExplicit(ssize_t ret, int savedErrno, Args&&... args) {
if ((__builtin_expect((ret == -1), 0))) {
throwSystemErrorExplicit(savedErrno, std::forward<Args>(args)...);
}
}
template <class... Args>
void checkFopenError(FILE* fp, Args&&... args) {
if ((__builtin_expect((!fp), 0))) {
throwSystemError(std::forward<Args>(args)...);
}
}
template <class... Args>
void checkFopenErrorExplicit(FILE* fp, int savedErrno, Args&&... args) {
if ((__builtin_expect((!fp), 0))) {
throwSystemErrorExplicit(savedErrno, std::forward<Args>(args)...);
}
}
// # 142 "tlm/deps/folly.exploded/include/folly/Exception.h" 3 4
} // namespace folly
// # 31 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/Function.h" 1 3 4
// # 219 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
// # 233 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
namespace folly {
template <typename FunctionType>
class Function;
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const> constCastFunction(
Function<ReturnType(Args...)>&&) noexcept;
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) noexcept>&&) noexcept;
namespace detail {
namespace function {
enum class Op { MOVE, NUKE, HEAP };
union Data {
Data() {
}
void* big;
std::aligned_storage<6 * sizeof(void*)>::type tiny;
};
template <typename Fun, typename = Fun*>
using IsSmall = Conjunction<bool_constant<(sizeof(Fun) <= sizeof(Data::tiny))>,
std::is_nothrow_move_constructible<Fun>>;
using SmallTag = std::true_type;
using HeapTag = std::false_type;
template <typename T>
struct NotFunction : std::true_type {};
template <typename T>
struct NotFunction<Function<T>> : std::false_type {};
template <typename T>
using EnableIfNotFunction =
typename std::enable_if<NotFunction<T>::value>::type;
struct CoerceTag {};
template <typename, typename T>
struct IsFunctionNullptrTestable : std::false_type {};
template <typename T>
struct IsFunctionNullptrTestable<
void_t<decltype(static_cast<bool>(static_cast<T const&>(T(nullptr)) ==
nullptr))>,
T> : std::true_type {};
template <typename T>
constexpr std::enable_if_t<!IsFunctionNullptrTestable<void, T>::value,
std::false_type>
isEmptyFunction(T const&) {
return {};
}
template <typename T>
constexpr std::enable_if_t<IsFunctionNullptrTestable<void, T>::value, bool>
isEmptyFunction(T const& t) {
return static_cast<bool>(t == nullptr);
}
template <typename F, typename... Args>
using CallableResult = decltype(std::declval<F>()(std::declval<Args>()...));
template <typename From,
typename To,
typename =
typename std::enable_if<!std::is_reference<To>::value ||
std::is_reference<From>::value>::type>
using SafeResultOf = decltype(static_cast<To>(std::declval<From>()));
// # 320 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
template <typename T>
using CallArg = conditional_t<is_trivially_copyable<T>::value, T, T&&>;
template <typename F, typename R, typename... A>
class FunctionTraitsSharedProxy {
std::shared_ptr<Function<F>> sp_;
public:
explicit FunctionTraitsSharedProxy(std::nullptr_t) noexcept {
}
explicit FunctionTraitsSharedProxy(Function<F>&& func)
: sp_(func ? std::make_shared<Function<F>>(std::move(func))
: std::shared_ptr<Function<F>>()) {
}
R operator()(A&&... args) const {
if (!sp_) {
throw_exception<std::bad_function_call>();
}
return (*sp_)(static_cast<A&&>(args)...);
}
explicit operator bool() const noexcept {
return sp_ != nullptr;
}
friend bool operator==(FunctionTraitsSharedProxy<F, R, A...> const& proxy,
std::nullptr_t) noexcept {
return proxy.sp_ == nullptr;
}
friend bool operator!=(FunctionTraitsSharedProxy<F, R, A...> const& proxy,
std::nullptr_t) noexcept {
return proxy.sp_ != nullptr;
}
friend bool operator==(
std::nullptr_t,
FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept {
return proxy.sp_ == nullptr;
}
friend bool operator!=(
std::nullptr_t,
FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept {
return proxy.sp_ != nullptr;
}
};
template <typename FunctionType>
struct FunctionTraits;
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...)> {
using Call = ReturnType (*)(CallArg<Args>..., Data&);
using IsConst = std::false_type;
using ConstSignature = ReturnType(Args...) const;
using NonConstSignature = ReturnType(Args...);
using OtherSignature = ConstSignature;
template <typename F>
using ResultOf =
SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>;
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) {
auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) {
auto& fn = *static_cast<Fun*>(p.big);
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
static ReturnType uninitCall(CallArg<Args>..., Data&) {
throw_exception<std::bad_function_call>();
}
ReturnType operator()(Args... args) {
auto& fn = *static_cast<Function<NonConstSignature>*>(this);
return fn.call_(static_cast<Args&&>(args)..., fn.data_);
}
using SharedProxy =
FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>;
};
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...) const> {
using Call = ReturnType (*)(CallArg<Args>..., Data&);
using IsConst = std::true_type;
using ConstSignature = ReturnType(Args...) const;
using NonConstSignature = ReturnType(Args...);
using OtherSignature = NonConstSignature;
template <typename F>
using ResultOf =
SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>,
ReturnType>;
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) {
auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) {
auto& fn = *static_cast<const Fun*>(p.big);
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
static ReturnType uninitCall(CallArg<Args>..., Data&) {
throw_exception<std::bad_function_call>();
}
ReturnType operator()(Args... args) const {
auto& fn = *static_cast<const Function<ConstSignature>*>(this);
return fn.call_(static_cast<Args&&>(args)..., fn.data_);
}
using SharedProxy =
FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>;
};
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...) noexcept> {
using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept;
using IsConst = std::false_type;
using ConstSignature = ReturnType(Args...) const noexcept;
using NonConstSignature = ReturnType(Args...) noexcept;
using OtherSignature = ConstSignature;
template <typename F>
using ResultOf =
SafeResultOf<CallableResult<std::decay_t<F>&, Args...>, ReturnType>;
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
auto& fn = *static_cast<Fun*>(p.big);
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
terminate_with<std::bad_function_call>();
}
ReturnType operator()(Args... args) noexcept {
auto& fn = *static_cast<Function<NonConstSignature>*>(this);
return fn.call_(static_cast<Args&&>(args)..., fn.data_);
}
using SharedProxy =
FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>;
};
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...) const noexcept> {
using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept;
using IsConst = std::true_type;
using ConstSignature = ReturnType(Args...) const noexcept;
using NonConstSignature = ReturnType(Args...) noexcept;
using OtherSignature = NonConstSignature;
template <typename F>
using ResultOf =
SafeResultOf<CallableResult<const std::decay_t<F>&, Args...>,
ReturnType>;
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
auto& fn = *static_cast<const Fun*>(p.big);
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
}
static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
throw_exception<std::bad_function_call>();
}
ReturnType operator()(Args... args) const noexcept {
auto& fn = *static_cast<const Function<ConstSignature>*>(this);
return fn.call_(static_cast<Args&&>(args)..., fn.data_);
}
using SharedProxy =
FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>;
};
template <typename Fun>
std::size_t execSmall(Op o, Data* src, Data* dst) {
switch (o) {
case Op::MOVE:
::new (static_cast<void*>(&dst->tiny)) Fun(
std::move(*static_cast<Fun*>(static_cast<void*>(&src->tiny))));
[[fallthrough]];
case Op::NUKE:
static_cast<Fun*>(static_cast<void*>(&src->tiny))->~Fun();
break;
case Op::HEAP:
break;
}
return 0U;
}
template <typename Fun>
std::size_t execBig(Op o, Data* src, Data* dst) {
switch (o) {
case Op::MOVE:
dst->big = src->big;
src->big = nullptr;
break;
case Op::NUKE:
delete static_cast<Fun*>(src->big);
break;
case Op::HEAP:
break;
}
return sizeof(Fun);
}
} // namespace function
} // namespace detail
template <typename FunctionType>
class Function final : private detail::function::FunctionTraits<FunctionType> {
using Data = detail::function::Data;
using Op = detail::function::Op;
using SmallTag = detail::function::SmallTag;
using HeapTag = detail::function::HeapTag;
using CoerceTag = detail::function::CoerceTag;
using Traits = detail::function::FunctionTraits<FunctionType>;
using Call = typename Traits::Call;
using Exec = std::size_t (*)(Op, Data*, Data*);
template <typename Fun>
using IsSmall = detail::function::IsSmall<Fun>;
mutable Data data_{};
Call call_{&Traits::uninitCall};
Exec exec_{nullptr};
std::size_t exec(Op o, Data* src, Data* dst) const {
if (!exec_) {
return 0U;
}
return exec_(o, src, dst);
}
friend Traits;
friend Function<typename Traits::ConstSignature> folly::constCastFunction<>(
Function<typename Traits::NonConstSignature>&&) noexcept;
friend class Function<typename Traits::OtherSignature>;
template <typename Fun>
Function(Fun&& fun, SmallTag) noexcept {
using FunT = typename std::decay<Fun>::type;
if (!detail::function::isEmptyFunction(fun)) {
::new (static_cast<void*>(&data_.tiny))
FunT(static_cast<Fun&&>(fun));
call_ = &Traits::template callSmall<FunT>;
exec_ = &detail::function::execSmall<FunT>;
}
}
template <typename Fun>
Function(Fun&& fun, HeapTag) {
using FunT = typename std::decay<Fun>::type;
if (!detail::function::isEmptyFunction(fun)) {
data_.big = new FunT(static_cast<Fun&&>(fun));
call_ = &Traits::template callBig<FunT>;
exec_ = &detail::function::execBig<FunT>;
}
}
template <typename Signature>
Function(Function<Signature>&& that, CoerceTag)
: Function(static_cast<Function<Signature>&&>(that), HeapTag{}) {
}
Function(Function<typename Traits::OtherSignature>&& that,
CoerceTag) noexcept
: call_(that.call_), exec_(that.exec_) {
that.call_ = &Traits::uninitCall;
that.exec_ = nullptr;
exec(Op::MOVE, &that.data_, &data_);
}
public:
Function() = default;
Function(const Function&) = delete;
// # 708 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
that.call_ = &Traits::uninitCall;
that.exec_ = nullptr;
exec(Op::MOVE, &that.data_, &data_);
}
Function(std::nullptr_t) noexcept {
}
// # 740 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
template <typename Fun,
typename = detail::function::EnableIfNotFunction<Fun>,
typename = typename Traits::template ResultOf<Fun>>
Function(Fun fun) noexcept(
IsSmall<Fun>::value&& noexcept(Fun(std::declval<Fun>())))
: Function(std::move(fun), IsSmall<Fun>{}) {
}
// # 757 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
template <
typename Signature,
typename = typename Traits::template ResultOf<Function<Signature>>>
Function(Function<Signature>&& that) noexcept(
noexcept(Function(std::move(that), CoerceTag{})))
: Function(std::move(that), CoerceTag{}) {
}
template <typename Member,
typename Class,
typename = decltype(Function(std::mem_fn((Member Class::*)0)))>
Function(Member Class::*ptr) noexcept {
if (ptr) {
*this = std::mem_fn(ptr);
}
}
~Function() {
exec(Op::NUKE, &data_, nullptr);
}
Function& operator=(const Function&) = delete;
// # 802 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
Function& operator=(Function&& that) noexcept {
// # 813 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
this->~Function();
::new (this) Function(std::move(that));
return *this;
}
// # 826 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
template <typename Fun, typename = decltype(Function(std::declval<Fun>()))>
Function& operator=(Fun fun) noexcept(
noexcept(Function(std::declval<Fun>()))) {
if (noexcept(Function(std::declval<Fun>()))) {
this->~Function();
::new (this) Function(std::move(fun));
} else {
Function(std::move(fun)).swap(*this);
}
return *this;
}
template <
typename Signature,
typename = typename Traits::template ResultOf<Function<Signature>>>
Function& operator=(Function<Signature>&& that) noexcept(
noexcept(Function(std::move(that)))) {
return (*this = Function(std::move(that)));
}
Function& operator=(std::nullptr_t) noexcept {
return (*this = Function());
}
template <typename Member, typename Class>
auto operator=(Member Class::*ptr) noexcept
-> decltype(operator=(std::mem_fn(ptr))) {
return ptr ? (*this = std::mem_fn(ptr)) : (*this = Function());
}
using Traits::operator();
void swap(Function& that) noexcept {
std::swap(*this, that);
}
explicit operator bool() const noexcept {
return exec_ != nullptr;
}
std::size_t heapAllocatedMemory() const noexcept {
return exec(Op::HEAP, nullptr, nullptr);
}
using typename Traits::SharedProxy;
SharedProxy asSharedProxy() && {
return SharedProxy{std::move(*this)};
}
std::function<typename Traits::NonConstSignature> asStdFunction() && {
return std::move(*this).asSharedProxy();
}
};
template <typename FunctionType>
void swap(Function<FunctionType>& lhs, Function<FunctionType>& rhs) noexcept {
lhs.swap(rhs);
}
template <typename FunctionType>
bool operator==(const Function<FunctionType>& fn, std::nullptr_t) {
return !fn;
}
template <typename FunctionType>
bool operator==(std::nullptr_t, const Function<FunctionType>& fn) {
return !fn;
}
template <typename FunctionType>
bool operator!=(const Function<FunctionType>& fn, std::nullptr_t) {
return !(fn == nullptr);
}
template <typename FunctionType>
bool operator!=(std::nullptr_t, const Function<FunctionType>& fn) {
return !(nullptr == fn);
}
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const> constCastFunction(
Function<ReturnType(Args...)>&& that) noexcept {
return Function<ReturnType(Args...) const>{std::move(that),
detail::function::CoerceTag{}};
}
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const> constCastFunction(
Function<ReturnType(Args...) const>&& that) noexcept {
return std::move(that);
}
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) noexcept>&& that) noexcept {
return Function<ReturnType(Args...) const noexcept>{
std::move(that), detail::function::CoerceTag{}};
}
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) const noexcept>&& that) noexcept {
return std::move(that);
}
// # 998 "tlm/deps/folly.exploded/include/folly/Function.h" 3 4
template <typename FunctionType>
class FunctionRef;
template <typename ReturnType, typename... Args>
class FunctionRef<ReturnType(Args...)> final {
template <typename Arg>
using CallArg = detail::function::CallArg<Arg>;
using Call = ReturnType (*)(CallArg<Args>..., void*);
static ReturnType uninitCall(CallArg<Args>..., void*) {
throw_exception<std::bad_function_call>();
}
template <typename Fun>
static ReturnType call(CallArg<Args>... args, void* object) {
using Pointer = std::add_pointer_t<Fun>;
return static_cast<ReturnType>(
invoke(static_cast<Fun&&>(*static_cast<Pointer>(object)),
static_cast<Args&&>(args)...));
}
void* object_{nullptr};
Call call_{&FunctionRef::uninitCall};
public:
constexpr FunctionRef() = default;
constexpr explicit FunctionRef(std::nullptr_t) noexcept {
}
template <
typename Fun,
typename std::enable_if<
Conjunction<Negation<std::is_same<FunctionRef,
std::decay_t<Fun>>>,
is_invocable_r<ReturnType, Fun&&, Args&&...>>::
value,
int>::type = 0>
constexpr FunctionRef(Fun&& fun) noexcept
: object_(const_cast<void*>(
static_cast<void const*>(std::addressof(fun)))),
call_(&FunctionRef::template call<Fun>) {
}
ReturnType operator()(Args... args) const {
return call_(static_cast<Args&&>(args)..., object_);
}
constexpr explicit operator bool() const noexcept {
return object_;
}
constexpr friend bool operator==(FunctionRef<ReturnType(Args...)> ref,
std::nullptr_t) noexcept {
return ref.object_ == nullptr;
}
constexpr friend bool operator!=(FunctionRef<ReturnType(Args...)> ref,
std::nullptr_t) noexcept {
return ref.object_ != nullptr;
}
constexpr friend bool operator==(
std::nullptr_t, FunctionRef<ReturnType(Args...)> ref) noexcept {
return ref.object_ == nullptr;
}
constexpr friend bool operator!=(
std::nullptr_t, FunctionRef<ReturnType(Args...)> ref) noexcept {
return ref.object_ != nullptr;
}
};
} // namespace folly
// # 32 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
namespace folly {
// # 85 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
template <typename Range, typename Func>
constexpr Func for_each(Range&& range, Func func);
namespace for_each_detail {
enum class LoopControl : bool { BREAK, CONTINUE };
}
constexpr auto loop_break = for_each_detail::LoopControl::BREAK;
constexpr auto loop_continue = for_each_detail::LoopControl::CONTINUE;
// # 121 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
template <typename Sequence, typename Index>
constexpr decltype(auto) fetch(Sequence&& sequence, Index&& index);
} // namespace folly
// # 162 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
namespace folly {
namespace detail {
// # 177 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
template <class T, class U>
typename std::enable_if<
(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
(std::is_pointer<T>::value && std::is_pointer<U>::value),
bool>::type
notThereYet(T& iter, const U& end) {
return iter < end;
}
template <class T, class U>
typename std::enable_if<
!((std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) ||
(std::is_pointer<T>::value && std::is_pointer<U>::value)),
bool>::type
notThereYet(T& iter, const U& end) {
return iter != end;
}
} // namespace detail
} // namespace folly
// # 209 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 3 4
// # 18 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 2 3 4
// # 30 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 3 4
namespace folly {
namespace for_each_detail {
namespace adl {
using std::begin;
using std::end;
using std::get;
template <std::size_t Index, typename Type>
auto adl_get(Type&& instance) -> decltype(get<Index>(std::declval<Type>())) {
return get<Index>(std::forward<Type>(instance));
}
template <typename Type>
auto adl_begin(Type&& instance) -> decltype(begin(instance)) {
return begin(instance);
}
template <typename Type>
auto adl_end(Type&& instance) -> decltype(end(instance)) {
return end(instance);
}
} // namespace adl
template <typename T>
using EnableIfMemberGetFound =
void_t<decltype(std::declval<T>().template get<0>())>;
template <typename, typename T>
struct IsMemberGetFound : std::false_type {};
template <typename T>
struct IsMemberGetFound<EnableIfMemberGetFound<T>, T> : std::true_type {};
template <std::size_t Index,
typename Type,
std::enable_if_t<!IsMemberGetFound<void, Type>::value, int> = 0>
auto get_impl(Type&& instance)
-> decltype(adl::adl_get<Index>(static_cast<Type&&>(instance))) {
return adl::adl_get<Index>(static_cast<Type&&>(instance));
}
template <std::size_t Index,
typename Type,
std::enable_if_t<IsMemberGetFound<void, Type>::value, int> = 0>
auto get_impl(Type&& instance)
-> decltype(static_cast<Type&&>(instance).template get<Index>()) {
return static_cast<Type&&>(instance).template get<Index>();
}
template <typename Type, typename T = typename std::decay<Type>::type>
using EnableIfTuple = void_t<decltype(get_impl<0>(std::declval<T>())),
decltype(std::tuple_size<T>::value)>;
template <typename, typename T>
struct IsTuple : std::false_type {};
template <typename T>
struct IsTuple<EnableIfTuple<T>, T> : std::true_type {};
template <typename Type, typename T = typename std::decay<Type>::type>
using EnableIfRange = void_t<decltype(adl::adl_begin(std::declval<T>())),
decltype(adl::adl_end(std::declval<T>()))>;
template <typename, typename T>
struct IsRange : std::false_type {};
template <typename T>
struct IsRange<EnableIfRange<T>, T> : std::true_type {};
struct TupleTag {};
struct RangeTag {};
template <typename Sequence>
using SequenceTag =
std::conditional_t<IsRange<void, Sequence>::value, RangeTag, TupleTag>;
struct BeginAddTag {};
struct IndexingTag {};
template <typename Func, typename Item, typename Iter>
using ForEachImplTag = std::conditional_t<
is_invocable_v<Func, Item, index_constant<0>, Iter>,
index_constant<3>,
std::conditional_t<is_invocable_v<Func, Item, index_constant<0>>,
index_constant<2>,
std::conditional_t<is_invocable_v<Func, Item>,
index_constant<1>,
void>>>;
template <
typename Func,
typename... Args,
std::enable_if_t<is_invocable_r_v<LoopControl, Func, Args...>, int> = 0>
LoopControl invoke_returning_loop_control(Func&& f, Args&&... a) {
return static_cast<Func&&>(f)(static_cast<Args&&>(a)...);
}
template <typename Func,
typename... Args,
std::enable_if_t<!is_invocable_r_v<LoopControl, Func, Args...>, int> =
0>
LoopControl invoke_returning_loop_control(Func&& f, Args&&... a) {
static_assert(std::is_void<invoke_result_t<Func, Args...>>::value,
"return either LoopControl or void");
return static_cast<Func&&>(f)(static_cast<Args&&>(a)...), loop_continue;
}
template <typename Sequence, typename Func>
void for_each_range_impl(index_constant<3>, Sequence&& range, Func& func) {
auto first = adl::adl_begin(range);
auto last = adl::adl_end(range);
for (auto index = std::size_t{0}; first != last; ++index) {
auto next = std::next(first);
auto control =
invoke_returning_loop_control(func, *first, index, first);
if (loop_break == control) {
break;
}
first = next;
}
}
template <typename Sequence, typename Func>
void for_each_range_impl(index_constant<2>, Sequence&& range, Func& func) {
auto three_arg_adaptor =
[&func](auto&& ele, auto index, auto) -> decltype(auto) {
return func(std::forward<decltype(ele)>(ele), index);
};
for_each_range_impl(index_constant<3>{},
std::forward<Sequence>(range),
three_arg_adaptor);
}
template <typename Sequence, typename Func>
void for_each_range_impl(index_constant<1>, Sequence&& range, Func& func) {
auto three_arg_adaptor = [&func](auto&& ele, auto, auto) -> decltype(auto) {
return func(std::forward<decltype(ele)>(ele));
};
for_each_range_impl(index_constant<3>{},
std::forward<Sequence>(range),
three_arg_adaptor);
}
template <typename Sequence, typename Func, std::size_t... Indices>
void for_each_tuple_impl(std::index_sequence<Indices...>,
Sequence&& seq,
Func& func) {
using _ = int[];
auto control = loop_continue;
void(_{(((control == loop_continue)
? (control = invoke_returning_loop_control(
func,
get_impl<Indices>(std::forward<Sequence>(seq)),
index_constant<Indices>{}))
: (loop_continue)),
0)...});
}
// # 241 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 3 4
template <typename Sequence, typename Func>
void for_each_tuple_impl(index_constant<2>, Sequence&& seq, Func& func) {
using size = std::tuple_size<typename std::decay<Sequence>::type>;
for_each_tuple_impl(std::make_index_sequence<size::value>{},
std::forward<Sequence>(seq),
func);
}
template <typename Sequence, typename Func>
void for_each_tuple_impl(index_constant<1>, Sequence&& seq, Func& func) {
auto two_arg_adaptor = [&func](auto&& ele, auto) -> decltype(auto) {
return func(std::forward<decltype(ele)>(ele));
};
for_each_tuple_impl(
index_constant<2>{}, std::forward<Sequence>(seq), two_arg_adaptor);
}
// # 269 "tlm/deps/folly.exploded/include/folly/container/Foreach-inl.h" 3 4
template <typename Sequence, typename Func>
void for_each_impl(TupleTag, Sequence&& range, Func& func) {
using type = decltype(get_impl<0>(std::declval<Sequence>()));
using tag = ForEachImplTag<Func, type, void>;
static_assert(!std::is_same<tag, void>::value, "unknown invocability");
for_each_tuple_impl(tag{}, std::forward<Sequence>(range), func);
}
template <typename Sequence, typename Func>
void for_each_impl(RangeTag, Sequence&& range, Func& func) {
using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
using type = decltype(*std::declval<iter>());
using tag = ForEachImplTag<Func, type, iter>;
static_assert(!std::is_same<tag, void>::value, "unknown invocability");
for_each_range_impl(tag{}, std::forward<Sequence>(range), func);
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(IndexingTag, Sequence&& sequence, Index&& index) {
return std::forward<Sequence>(sequence)[std::forward<Index>(index)];
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(BeginAddTag, Sequence&& sequence, Index index) {
return *(adl::adl_begin(std::forward<Sequence>(sequence)) + index);
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(TupleTag, Sequence&& sequence, Index index) {
return get_impl<index>(std::forward<Sequence>(sequence));
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(RangeTag, Sequence&& sequence, Index&& index) {
using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
using iter_traits = std::iterator_traits<remove_cvref_t<iter>>;
using iter_cat = typename iter_traits::iterator_category;
using tag = std::conditional_t<
std::is_same<iter_cat, std::random_access_iterator_tag>::value,
BeginAddTag,
IndexingTag>;
return fetch_impl(tag{},
std::forward<Sequence>(sequence),
std::forward<Index>(index));
}
} // namespace for_each_detail
template <typename Sequence, typename Func>
constexpr Func for_each(Sequence&& sequence, Func func) {
namespace fed = for_each_detail;
using tag = fed::SequenceTag<Sequence>;
fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func);
return func;
}
template <typename Sequence, typename Index>
constexpr decltype(auto) fetch(Sequence&& sequence, Index&& index) {
namespace fed = for_each_detail;
using tag = fed::SequenceTag<Sequence>;
return for_each_detail::fetch_impl(tag{},
std::forward<Sequence>(sequence),
std::forward<Index>(index));
}
} // namespace folly
// # 210 "tlm/deps/folly.exploded/include/folly/container/Foreach.h" 2 3 4
// # 36 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/AtFork.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/AtFork.h" 3 4
namespace folly {
namespace detail {
struct AtFork {
static void init();
static void registerHandler(void const* handle,
folly::Function<bool()> prepare,
folly::Function<void()> parent,
folly::Function<void()> child);
static void unregisterHandler(void const* handle);
};
} // namespace detail
} // namespace folly
// # 37 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h" 1
// 3 4 # 33
// "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h" 3 4
// # 42 "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h"
// 3 4 # 43
// "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/synchronization/detail/Sleeper.h"
// 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/synchronization/detail/Sleeper.h" 3 4
// # 29 "tlm/deps/folly.exploded/include/folly/synchronization/detail/Sleeper.h"
// 3 4
namespace folly {
namespace detail {
class Sleeper {
static const uint32_t kMaxActiveSpin = 4000;
uint32_t spinCount;
public:
Sleeper() noexcept : spinCount(0) {
}
static void sleep() noexcept {
struct timespec ts = {0, 500000};
nanosleep(&ts, nullptr);
}
void wait() noexcept {
if (spinCount < kMaxActiveSpin) {
++spinCount;
asm_volatile_pause();
} else {
sleep();
}
}
};
} // namespace detail
} // namespace folly
// # 51 "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h"
// 2 3 4
namespace folly {
// # 66 "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h"
// 3 4
struct MicroSpinLock {
enum { FREE = 0, LOCKED = 1 };
uint8_t lock_;
void init() noexcept {
payload()->store(FREE);
}
bool try_lock() noexcept {
bool ret = cas(FREE, LOCKED);
annotate_rwlock_try_acquired(this,
annotate_rwlock_level::wrlock,
ret,
"tlm/deps/folly.exploded/include/folly/"
"synchronization/MicroSpinLock.h",
80);
return ret;
}
void lock() noexcept {
detail::Sleeper sleeper;
while (!cas(FREE, LOCKED)) {
do {
sleeper.wait();
} while (payload()->load(std::memory_order_relaxed) == LOCKED);
}
(static_cast<bool>(payload()->load() == LOCKED)
? void(0)
: __assert_fail("payload()->load() == LOCKED",
"tlm/deps/folly.exploded/include/folly/"
"synchronization/MicroSpinLock.h",
91,
__extension__ __PRETTY_FUNCTION__));
annotate_rwlock_acquired(this,
annotate_rwlock_level::wrlock,
"tlm/deps/folly.exploded/include/folly/"
"synchronization/MicroSpinLock.h",
93);
}
void unlock() noexcept {
(static_cast<bool>(payload()->load() == LOCKED)
? void(0)
: __assert_fail("payload()->load() == LOCKED",
"tlm/deps/folly.exploded/include/folly/"
"synchronization/MicroSpinLock.h",
97,
__extension__ __PRETTY_FUNCTION__));
annotate_rwlock_released(this,
annotate_rwlock_level::wrlock,
"tlm/deps/folly.exploded/include/folly/"
"synchronization/MicroSpinLock.h",
99);
payload()->store(FREE, std::memory_order_release);
}
private:
std::atomic<uint8_t>* payload() noexcept {
return reinterpret_cast<std::atomic<uint8_t>*>(&this->lock_);
}
bool cas(uint8_t compare, uint8_t newVal) noexcept {
return std::atomic_compare_exchange_strong_explicit(
payload(),
&compare,
newVal,
std::memory_order_acquire,
std::memory_order_relaxed);
}
};
static_assert(std::is_pod<MicroSpinLock>::value,
"MicroSpinLock must be kept a POD type.");
// # 129 "tlm/deps/folly.exploded/include/folly/synchronization/MicroSpinLock.h"
// 3 4
template <class T, size_t N>
struct alignas(max_align_v) SpinLockArray {
T& operator[](size_t i) noexcept {
return data_[i].lock;
}
const T& operator[](size_t i) const noexcept {
return data_[i].lock;
}
constexpr size_t size() const noexcept {
return N;
}
private:
struct PaddedSpinLock {
PaddedSpinLock() : lock() {
}
T lock;
char padding[hardware_destructive_interference_size - sizeof(T)];
};
static_assert(sizeof(PaddedSpinLock) ==
hardware_destructive_interference_size,
"Invalid size of PaddedSpinLock");
static_assert(max_align_v > 0 &&
hardware_destructive_interference_size %
max_align_v ==
0 &&
sizeof(T) <= max_align_v,
"T can cross cache line boundaries");
char padding_[hardware_destructive_interference_size];
std::array<PaddedSpinLock, N> data_;
};
typedef std::lock_guard<MicroSpinLock> MSLGuard;
} // namespace folly
// # 40 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/StaticSingletonManager.h" 1
// 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/detail/StaticSingletonManager.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/Singleton.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/Singleton.h" 3 4
namespace folly {
namespace detail {
struct DefaultTag {};
template <typename T>
struct DefaultMake {
struct Heap {
std::unique_ptr<T> ptr{std::make_unique<T>()};
operator T&() {
return *ptr;
}
};
using is_returnable = StrictDisjunction<bool_constant<201703L >= 201703ULL>,
std::is_copy_constructible<T>,
std::is_move_constructible<T>>;
using type = std::conditional_t<is_returnable::value, T, Heap>;
type operator()() const {
return type();
}
};
} // namespace detail
} // namespace folly
// # 26 "tlm/deps/folly.exploded/include/folly/detail/StaticSingletonManager.h"
// 2 3 4 # 1 "tlm/deps/folly.exploded/include/folly/lang/TypeInfo.h" 1 3 4 # 17
// "tlm/deps/folly.exploded/include/folly/lang/TypeInfo.h" 3 4
// # 33 "tlm/deps/folly.exploded/include/folly/lang/TypeInfo.h" 3 4
namespace folly {
template <typename T>
inline __attribute__((__always_inline__)) static std::type_info const*
type_info_of() {
return (&typeid(T));
}
template <typename T>
inline __attribute__((__always_inline__)) static std::type_info const*
type_info_of(T const& t) {
return (&typeid(t));
}
} // namespace folly
// # 27 "tlm/deps/folly.exploded/include/folly/detail/StaticSingletonManager.h"
// 2 3 4
namespace folly {
namespace detail {
class StaticSingletonManagerSansRtti {
public:
template <typename T, typename Tag>
__attribute__((__visibility__("default"))) inline
__attribute__((__always_inline__)) static T&
create() {
static std::atomic<T*> cache{};
auto const pointer = cache.load(std::memory_order_acquire);
return (__builtin_expect((!!pointer), 1)) ? *pointer
: create_<T, Tag>(cache);
}
private:
template <typename T, typename Tag>
__attribute__((__visibility__("default")))
__attribute__((__noinline__)) static T&
create_(std::atomic<T*>& cache) {
static Indestructible<T> instance;
cache.store(&*instance, std::memory_order_release);
return *instance;
}
};
class StaticSingletonManagerWithRtti {
public:
template <typename T, typename Tag>
__attribute__((__visibility__("default"))) inline
__attribute__((__always_inline__)) static T&
create() {
static Arg arg{{nullptr}, (&typeid(tag_t<T, Tag>)), make<T>};
auto const v = arg.cache.load(std::memory_order_acquire);
auto const p =
(__builtin_expect((!!v), 1)) ? v : create_<noexcept(T())>(arg);
return *static_cast<T*>(p);
}
private:
using Key = std::type_info;
using Make = void*();
using Cache = std::atomic<void*>;
struct Arg {
Cache cache;
Key const* key;
Make& make;
};
template <typename T>
static void* make() {
return new T();
}
template <bool Noexcept>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) static void*
create_(Arg& arg) noexcept(Noexcept) {
return create_(arg);
}
__attribute__((__noinline__)) static void* create_(Arg& arg);
};
using StaticSingletonManager =
std::conditional_t<kHasRtti,
StaticSingletonManagerWithRtti,
StaticSingletonManagerSansRtti>;
template <typename T, typename Tag>
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) T&
createGlobal() {
return StaticSingletonManager::create<T, Tag>();
}
} // namespace detail
} // namespace folly
// # 43 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 2 3 4
// # 56 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
namespace folly {
enum class TLPDestructionMode { THIS_THREAD, ALL_THREADS };
struct AccessModeStrict {};
namespace threadlocal_detail {
constexpr uint32_t kEntryIDInvalid = std::numeric_limits<uint32_t>::max();
struct ThreadEntry;
// # 75 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
struct ThreadEntryNode {
uint32_t id : 31;
bool isZero : 1;
ThreadEntry* parent;
ThreadEntry* prev;
ThreadEntry* next;
void initIfZero(bool locked);
void init(ThreadEntry* entry, uint32_t newId) {
id = newId;
isZero = false;
parent = prev = next = entry;
}
void initZero(ThreadEntry* entry, uint32_t newId) {
id = newId;
isZero = true;
parent = entry;
prev = next = nullptr;
}
inline __attribute__((__always_inline__)) bool empty() const {
return (next == parent);
}
inline __attribute__((__always_inline__)) bool zero() const {
return isZero;
}
inline __attribute__((__always_inline__)) ThreadEntry* getThreadEntry() {
return parent;
}
inline __attribute__((__always_inline__)) ThreadEntryNode* getPrev();
inline __attribute__((__always_inline__)) ThreadEntryNode* getNext();
void push_back(ThreadEntry* head);
void eraseZero();
};
struct ElementWrapper {
using DeleterFunType = void(void*, TLPDestructionMode);
bool dispose(TLPDestructionMode mode) {
if (ptr == nullptr) {
return false;
}
static_cast<void>(0),
!((__builtin_expect(!(deleter1 != nullptr), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/detail/ThreadLocalDetail.h",
131)
.stream()
<< "Check failed: "
"deleter1 != nullptr"
" ";
ownsDeleter ? (*deleter2)(ptr, mode) : (*deleter1)(ptr, mode);
return true;
}
void* release() {
auto retPtr = ptr;
if (ptr != nullptr) {
cleanup();
}
return retPtr;
}
template <class Ptr>
void set(Ptr p) {
auto guard = makeGuard([&] { delete p; });
static_cast<void>(0),
!((__builtin_expect(!(ptr == nullptr), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/detail/ThreadLocalDetail.h",
149)
.stream()
<< "Check failed: "
"ptr == nullptr"
" ";
static_cast<void>(0),
!((__builtin_expect(!(deleter1 == nullptr), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/detail/ThreadLocalDetail.h",
150)
.stream()
<< "Check failed: "
"deleter1 == nullptr"
" ";
if (p) {
node.initIfZero(true);
ptr = p;
deleter1 = [](void* pt, TLPDestructionMode) {
delete static_cast<Ptr>(pt);
};
ownsDeleter = false;
guard.dismiss();
}
}
template <class Ptr, class Deleter>
void set(Ptr p, const Deleter& d) {
auto guard = makeGuard([&] {
if (p) {
d(p, TLPDestructionMode::THIS_THREAD);
}
});
static_cast<void>(0),
!((__builtin_expect(!(ptr == nullptr), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/detail/ThreadLocalDetail.h",
170)
.stream()
<< "Check failed: "
"ptr == nullptr"
" ";
static_cast<void>(0),
!((__builtin_expect(!(deleter2 == nullptr), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/detail/ThreadLocalDetail.h",
171)
.stream()
<< "Check failed: "
"deleter2 == nullptr"
" ";
if (p) {
node.initIfZero(true);
ptr = p;
auto d2 = d;
deleter2 = new std::function<DeleterFunType>(
[d2](void* pt, TLPDestructionMode mode) {
d2(static_cast<Ptr>(pt), mode);
});
ownsDeleter = true;
guard.dismiss();
}
}
void cleanup() {
if (ownsDeleter) {
delete deleter2;
}
ptr = nullptr;
deleter1 = nullptr;
ownsDeleter = false;
}
void* ptr;
union {
DeleterFunType* deleter1;
std::function<DeleterFunType>* deleter2;
};
bool ownsDeleter;
ThreadEntryNode node;
};
struct StaticMetaBase;
struct ThreadEntryList;
// # 214 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
struct ThreadEntry {
ElementWrapper* elements{nullptr};
std::atomic<size_t> elementsCapacity{0};
ThreadEntryList* list{nullptr};
ThreadEntry* listNext{nullptr};
StaticMetaBase* meta{nullptr};
bool removed_{false};
uint64_t tid_os{};
aligned_storage_for_t<std::thread::id> tid_data{};
size_t getElementsCapacity() const noexcept {
return elementsCapacity.load(std::memory_order_relaxed);
}
void setElementsCapacity(size_t capacity) noexcept {
elementsCapacity.store(capacity, std::memory_order_relaxed);
}
std::thread::id& tid() {
return *reinterpret_cast<std::thread::id*>(&tid_data);
}
};
struct ThreadEntryList {
ThreadEntry* head{nullptr};
size_t count{0};
};
struct PthreadKeyUnregisterTester;
inline __attribute__((__always_inline__)) ThreadEntryNode*
ThreadEntryNode::getPrev() {
return &prev->elements[id].node;
}
inline __attribute__((__always_inline__)) ThreadEntryNode*
ThreadEntryNode::getNext() {
return &next->elements[id].node;
}
// # 265 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
class PthreadKeyUnregister {
public:
static constexpr size_t kMaxKeys = 1UL << 16;
~PthreadKeyUnregister() {
MSLGuard lg(lock_);
while (size_) {
pthread_key_delete(keys_[--size_]);
}
}
static void registerKey(pthread_key_t key) {
instance_.registerKeyImpl(key);
}
private:
constexpr PthreadKeyUnregister() : lock_(), size_(0), keys_() {
}
friend struct folly::threadlocal_detail::PthreadKeyUnregisterTester;
void registerKeyImpl(pthread_key_t key) {
MSLGuard lg(lock_);
if (size_ == kMaxKeys) {
throw std::logic_error(
"pthread_key limit has already been reached");
}
keys_[size_++] = key;
}
MicroSpinLock lock_;
size_t size_;
pthread_key_t keys_[kMaxKeys];
static PthreadKeyUnregister instance_;
};
struct StaticMetaBase {
class EntryID {
public:
std::atomic<uint32_t> value;
constexpr EntryID() : value(kEntryIDInvalid) {
}
EntryID(EntryID&& other) noexcept : value(other.value.load()) {
other.value = kEntryIDInvalid;
}
EntryID& operator=(EntryID&& other) noexcept {
(static_cast<bool>(this != &other)
? void(0)
: __assert_fail("this != &other",
"tlm/deps/folly.exploded/include/folly/"
"detail/ThreadLocalDetail.h",
324,
__extension__ __PRETTY_FUNCTION__));
value = other.value.load();
other.value = kEntryIDInvalid;
return *this;
}
EntryID(const EntryID& other) = delete;
EntryID& operator=(const EntryID& other) = delete;
uint32_t getOrInvalid() {
return value.load(std::memory_order_acquire);
}
uint32_t getOrAllocate(StaticMetaBase& meta) {
uint32_t id = getOrInvalid();
if (id != kEntryIDInvalid) {
return id;
}
return meta.allocate(this);
}
};
StaticMetaBase(ThreadEntry* (*threadEntry)(), bool strict);
__attribute__((__visibility__("default"))) static ThreadEntryList*
getThreadEntryList();
static bool dying();
static void onThreadExit(void* ptr);
uint32_t elementsCapacity() const;
uint32_t allocate(EntryID* ent);
void destroy(EntryID* ent);
void reserve(EntryID* id);
ElementWrapper& getElement(EntryID* ent);
void reserveHeadUnlocked(uint32_t id);
void pushBackLocked(ThreadEntry* t, uint32_t id);
void pushBackUnlocked(ThreadEntry* t, uint32_t id);
static ElementWrapper* reallocate(ThreadEntry* threadEntry,
uint32_t idval,
size_t& newCapacity);
uint32_t nextId_;
std::vector<uint32_t> freeIds_;
std::mutex lock_;
SharedMutex accessAllThreadsLock_;
pthread_key_t pthreadKey_;
ThreadEntry head_;
ThreadEntry* (*threadEntry_)();
bool strict_;
};
// # 404 "tlm/deps/folly.exploded/include/folly/detail/ThreadLocalDetail.h" 3 4
template <class Tag, class AccessMode>
struct StaticMeta final : StaticMetaBase {
StaticMeta()
: StaticMetaBase(&StaticMeta::getThreadEntrySlow,
std::is_same<AccessMode, AccessModeStrict>::value) {
detail::AtFork::registerHandler(this,
&StaticMeta::preFork,
&StaticMeta::onForkParent,
&StaticMeta::onForkChild);
}
static StaticMeta<Tag, AccessMode>& instance() {
return detail::createGlobal<StaticMeta<Tag, AccessMode>, void>();
}
__attribute__((__visibility__("default"))) inline
__attribute__((__always_inline__)) static ElementWrapper&
get(EntryID* ent) {
uint32_t id = ent->getOrInvalid();
static __thread ThreadEntry* threadEntry{};
static __thread size_t capacity{};
if ((__builtin_expect((capacity <= id), 0))) {
getSlowReserveAndCache(ent, id, threadEntry, capacity);
}
return threadEntry->elements[id];
}
__attribute__((__noinline__)) static void getSlowReserveAndCache(
EntryID* ent,
uint32_t& id,
ThreadEntry*& threadEntry,
size_t& capacity) {
auto& inst = instance();
threadEntry = inst.threadEntry_();
if ((__builtin_expect((threadEntry->getElementsCapacity() <= id), 0))) {
inst.reserve(ent);
id = ent->getOrInvalid();
}
capacity = threadEntry->getElementsCapacity();
(static_cast<bool>(capacity > id)
? void(0)
: __assert_fail("capacity > id",
"tlm/deps/folly.exploded/include/folly/detail/"
"ThreadLocalDetail.h",
452,
__extension__ __PRETTY_FUNCTION__));
}
__attribute__((__visibility__("default")))
__attribute__((__noinline__)) static ThreadEntry*
getThreadEntrySlow() {
auto& meta = instance();
auto key = meta.pthreadKey_;
ThreadEntry* threadEntry =
static_cast<ThreadEntry*>(pthread_getspecific(key));
if (!threadEntry) {
ThreadEntryList* threadEntryList = StaticMeta::getThreadEntryList();
static __thread ThreadEntry threadEntrySingleton;
threadEntry = &threadEntrySingleton;
if (!threadEntry->list) {
threadEntry->list = threadEntryList;
threadEntry->listNext = threadEntryList->head;
threadEntryList->head = threadEntry;
}
threadEntry->tid() = std::this_thread::get_id();
threadEntry->tid_os = folly::getOSThreadID();
threadEntryList->count++;
threadEntry->meta = &meta;
int ret = pthread_setspecific(key, threadEntry);
checkPosixError(ret, "pthread_setspecific failed");
}
return threadEntry;
}
static bool preFork() {
return instance().lock_.try_lock();
}
static void onForkParent() {
instance().lock_.unlock();
}
static void onForkChild() {
auto& head = instance().head_;
auto elementsCapacity = head.getElementsCapacity();
for (size_t i = 0u; i < elementsCapacity; ++i) {
head.elements[i].node.init(&head, static_cast<uint32_t>(i));
}
ThreadEntry* threadEntry = instance().threadEntry_();
elementsCapacity = threadEntry->getElementsCapacity();
for (size_t i = 0u; i < elementsCapacity; ++i) {
if (!threadEntry->elements[i].node.zero()) {
threadEntry->elements[i].node.initZero(
threadEntry, static_cast<uint32_t>(i));
threadEntry->elements[i].node.initIfZero(false);
}
}
instance().lock_.unlock();
}
};
} // namespace threadlocal_detail
} // namespace folly
// # 53 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 2 3 4
namespace folly {
template <class T, class Tag, class AccessMode>
class ThreadLocalPtr;
template <class T, class Tag = void, class AccessMode = void>
class ThreadLocal {
public:
constexpr ThreadLocal() : constructor_([]() { return new T(); }) {
}
template <typename F, std::enable_if_t<is_invocable_r_v<T*, F>, int> = 0>
explicit ThreadLocal(F&& constructor)
: constructor_(std::forward<F>(constructor)) {
}
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) T*
get() const {
auto const ptr = tlp_.get();
return (__builtin_expect((!!ptr), 1)) ? ptr : makeTlp();
}
inline __attribute__((__always_inline__))
__attribute__((__visibility__("hidden"))) T*
getIfExist() const {
return tlp_.get();
}
T* operator->() const {
return get();
}
T& operator*() const {
return *get();
}
void reset(T* newPtr = nullptr) {
tlp_.reset(newPtr);
}
typedef typename ThreadLocalPtr<T, Tag, AccessMode>::Accessor Accessor;
Accessor accessAllThreads() const {
return tlp_.accessAllThreads();
}
ThreadLocal(ThreadLocal&&) = default;
ThreadLocal& operator=(ThreadLocal&&) = default;
private:
ThreadLocal(const ThreadLocal&) = delete;
ThreadLocal& operator=(const ThreadLocal&) = delete;
__attribute__((__noinline__)) T* makeTlp() const {
auto const ptr = constructor_();
tlp_.reset(ptr);
return ptr;
}
mutable ThreadLocalPtr<T, Tag, AccessMode> tlp_;
std::function<T*()> constructor_;
};
// # 140 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 3 4
template <class T, class Tag = void, class AccessMode = void>
class ThreadLocalPtr {
private:
typedef threadlocal_detail::StaticMeta<Tag, AccessMode> StaticMeta;
using AccessAllThreadsEnabled = Negation<std::is_same<Tag, void>>;
public:
constexpr ThreadLocalPtr() : id_() {
}
ThreadLocalPtr(ThreadLocalPtr&& other) noexcept
: id_(std::move(other.id_)) {
}
ThreadLocalPtr& operator=(ThreadLocalPtr&& other) {
(static_cast<bool>(this != &other)
? void(0)
: __assert_fail("this != &other",
"tlm/deps/folly.exploded/include/folly/"
"ThreadLocal.h",
153,
__extension__ __PRETTY_FUNCTION__));
destroy();
id_ = std::move(other.id_);
return *this;
}
~ThreadLocalPtr() {
destroy();
}
T* get() const {
threadlocal_detail::ElementWrapper& w = StaticMeta::get(&id_);
return static_cast<T*>(w.ptr);
}
T* operator->() const {
return get();
}
T& operator*() const {
return *get();
}
T* release() {
auto rlock = getAccessAllThreadsLockReadHolderIfEnabled();
threadlocal_detail::ElementWrapper& w = StaticMeta::get(&id_);
return static_cast<T*>(w.release());
}
void reset(T* newPtr = nullptr) {
auto rlock = getAccessAllThreadsLockReadHolderIfEnabled();
auto guard = makeGuard([&] { delete newPtr; });
threadlocal_detail::ElementWrapper* w = &StaticMeta::get(&id_);
w->dispose(TLPDestructionMode::THIS_THREAD);
w = &StaticMeta::get(&id_);
w->cleanup();
guard.dismiss();
w->set(newPtr);
}
explicit operator bool() const {
return get() != nullptr;
}
template <typename SourceT,
typename Deleter,
typename = typename std::enable_if<
std::is_convertible<SourceT*, T*>::value>::type>
void reset(std::unique_ptr<SourceT, Deleter> source) {
auto deleter = [delegate = source.get_deleter()](
T* ptr, TLPDestructionMode) { delegate(ptr); };
reset(source.release(), deleter);
}
template <typename SourceT,
typename = typename std::enable_if<
std::is_convertible<SourceT*, T*>::value>::type>
void reset(std::unique_ptr<SourceT> source) {
reset(source.release());
}
// # 237 "tlm/deps/folly.exploded/include/folly/ThreadLocal.h" 3 4
template <class Deleter>
void reset(T* newPtr, const Deleter& deleter) {
auto rlock = getAccessAllThreadsLockReadHolderIfEnabled();
auto guard = makeGuard([&] {
if (newPtr) {
deleter(newPtr, TLPDestructionMode::THIS_THREAD);
}
});
threadlocal_detail::ElementWrapper* w = &StaticMeta::get(&id_);
w->dispose(TLPDestructionMode::THIS_THREAD);
w = &StaticMeta::get(&id_);
w->cleanup();
guard.dismiss();
w->set(newPtr, deleter);
}
class Accessor {
friend class ThreadLocalPtr<T, Tag, AccessMode>;
threadlocal_detail::StaticMetaBase& meta_;
SharedMutex* accessAllThreadsLock_;
std::mutex* lock_;
uint32_t id_;
public:
class Iterator;
friend class Iterator;
class Iterator {
friend class Accessor;
const Accessor* accessor_;
threadlocal_detail::ThreadEntryNode* e_;
void increment() {
e_ = e_->getNext();
incrementToValid();
}
void decrement() {
e_ = e_->getPrev();
decrementToValid();
}
const T& dereference() const {
return *static_cast<T*>(
e_->getThreadEntry()->elements[accessor_->id_].ptr);
}
T& dereference() {
return *static_cast<T*>(
e_->getThreadEntry()->elements[accessor_->id_].ptr);
}
bool equal(const Iterator& other) const {
return (accessor_->id_ == other.accessor_->id_ &&
e_ == other.e_);
}
explicit Iterator(const Accessor* accessor)
: accessor_(accessor),
e_(&accessor_->meta_.head_.elements[accessor_->id_].node) {
}
bool valid() const {
return (e_->getThreadEntry()->elements[accessor_->id_].ptr);
}
void incrementToValid() {
for (; e_ != &accessor_->meta_.head_.elements[accessor_->id_]
.node &&
!valid();
e_ = e_->getNext()) {
}
}
void decrementToValid() {
for (; e_ != &accessor_->meta_.head_.elements[accessor_->id_]
.node &&
!valid();
e_ = e_->getPrev()) {
}
}
public:
using difference_type = ssize_t;
using value_type = T;
using reference = T const&;
using pointer = T const*;
using iterator_category = std::bidirectional_iterator_tag;
Iterator& operator++() {
increment();
return *this;
}
Iterator& operator++(int) {
Iterator copy(*this);
increment();
return copy;
}
Iterator& operator--() {
decrement();
return *this;
}
Iterator& operator--(int) {
Iterator copy(*this);
decrement();
return copy;
}
T& operator*() {
return dereference();
}
T const& operator*() const {
return dereference();
}
T* operator->() {
return &dereference();
}
T const* operator->() const {
return &dereference();
}
bool operator==(Iterator const& rhs) const {
return equal(rhs);
}
bool operator!=(Iterator const& rhs) const {
return !equal(rhs);
}
std::thread::id getThreadId() const {
return e_->getThreadEntry()->tid();
}
uint64_t getOSThreadId() const {
return e_->getThreadEntry()->tid_os;
}
};
~Accessor() {
release();
}
Iterator begin() const {
return ++Iterator(this);
}
Iterator end() const {
return Iterator(this);
}
Accessor(const Accessor&) = delete;
Accessor& operator=(const Accessor&) = delete;
Accessor(Accessor&& other) noexcept
: meta_(other.meta_),
accessAllThreadsLock_(other.accessAllThreadsLock_),
lock_(other.lock_),
id_(other.id_) {
other.id_ = 0;
other.accessAllThreadsLock_ = nullptr;
other.lock_ = nullptr;
}
Accessor& operator=(Accessor&& other) noexcept {
(static_cast<bool>(&meta_ == &other.meta_)
? void(0)
: __assert_fail("&meta_ == &other.meta_",
"tlm/deps/folly.exploded/include/folly/"
"ThreadLocal.h",
419,
__extension__ __PRETTY_FUNCTION__));
(static_cast<bool>(lock_ == nullptr)
? void(0)
: __assert_fail("lock_ == nullptr",
"tlm/deps/folly.exploded/include/folly/"
"ThreadLocal.h",
420,
__extension__ __PRETTY_FUNCTION__));
using std::swap;
swap(accessAllThreadsLock_, other.accessAllThreadsLock_);
swap(lock_, other.lock_);
swap(id_, other.id_);
}
Accessor()
: meta_(threadlocal_detail::StaticMeta<Tag,
AccessMode>::instance()),
accessAllThreadsLock_(nullptr),
lock_(nullptr),
id_(0) {
}
private:
explicit Accessor(uint32_t id)
: meta_(threadlocal_detail::StaticMeta<Tag,
AccessMode>::instance()),
accessAllThreadsLock_(&meta_.accessAllThreadsLock_),
lock_(&meta_.lock_) {
accessAllThreadsLock_->lock();
lock_->lock();
id_ = id;
}
void release() {
if (lock_) {
lock_->unlock();
static_cast<void>(0),
!((__builtin_expect(!(accessAllThreadsLock_ != nullptr),
0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/"
"include/folly/ThreadLocal.h",
446)
.stream()
<< "Check failed: "
"accessAllThreadsLock_ != "
"nullptr"
" ";
accessAllThreadsLock_->unlock();
id_ = 0;
lock_ = nullptr;
accessAllThreadsLock_ = nullptr;
}
}
};
Accessor accessAllThreads() const {
static_assert(
AccessAllThreadsEnabled::value,
"Must use a unique Tag to use the accessAllThreads feature");
return Accessor(id_.getOrAllocate(StaticMeta::instance()));
}
private:
void destroy() {
StaticMeta::instance().destroy(&id_);
}
ThreadLocalPtr(const ThreadLocalPtr&) = delete;
ThreadLocalPtr& operator=(const ThreadLocalPtr&) = delete;
static auto getAccessAllThreadsLockReadHolderIfEnabled() {
return SharedMutex::ReadHolder(
AccessAllThreadsEnabled::value
? &StaticMeta::instance().accessAllThreadsLock_
: nullptr);
}
mutable typename StaticMeta::EntryID id_;
};
namespace threadlocal_detail {
template <typename>
struct static_meta_of;
template <typename T, typename Tag, typename AccessMode>
struct static_meta_of<ThreadLocalPtr<T, Tag, AccessMode>> {
using type = StaticMeta<Tag, AccessMode>;
};
template <typename T, typename Tag, typename AccessMode>
struct static_meta_of<ThreadLocal<T, Tag, AccessMode>> {
using type = StaticMeta<Tag, AccessMode>;
};
} // namespace threadlocal_detail
} // namespace folly
// # 29 "tlm/deps/folly.exploded/include/folly/ThreadCachedInt.h" 2 3 4
namespace folly {
template <class IntT, class Tag = IntT>
class ThreadCachedInt {
struct IntCache;
public:
explicit ThreadCachedInt(IntT initialVal = 0, uint32_t cacheSize = 1000)
: target_(initialVal), cacheSize_(cacheSize) {
}
ThreadCachedInt(const ThreadCachedInt&) = delete;
ThreadCachedInt& operator=(const ThreadCachedInt&) = delete;
void increment(IntT inc) {
auto cache = cache_.get();
if ((__builtin_expect((cache == nullptr), 0))) {
cache = new IntCache(*this);
cache_.reset(cache);
}
cache->increment(inc);
}
IntT readFast() const {
return target_.load(std::memory_order_relaxed);
}
IntT readFull() const {
const auto accessor = cache_.accessAllThreads();
IntT ret = readFast();
for (const auto& cache : accessor) {
if (!cache.reset_.load(std::memory_order_acquire)) {
ret += cache.val_.load(std::memory_order_relaxed);
}
}
return ret;
}
IntT readFastAndReset() {
return target_.exchange(0, std::memory_order_release);
}
IntT readFullAndReset() {
auto accessor = cache_.accessAllThreads();
IntT ret = readFastAndReset();
for (auto& cache : accessor) {
if (!cache.reset_.load(std::memory_order_acquire)) {
ret += cache.val_.load(std::memory_order_relaxed);
cache.reset_.store(true, std::memory_order_release);
}
}
return ret;
}
void setCacheSize(uint32_t newSize) {
cacheSize_.store(newSize, std::memory_order_release);
}
uint32_t getCacheSize() const {
return cacheSize_.load();
}
ThreadCachedInt& operator+=(IntT inc) {
increment(inc);
return *this;
}
ThreadCachedInt& operator-=(IntT inc) {
increment(-inc);
return *this;
}
ThreadCachedInt& operator++() {
increment(1);
return *this;
}
ThreadCachedInt& operator--() {
increment(IntT(-1));
return *this;
}
void set(IntT newVal) {
for (auto& cache : cache_.accessAllThreads()) {
cache.reset_.store(true, std::memory_order_release);
}
target_.store(newVal, std::memory_order_release);
}
private:
std::atomic<IntT> target_;
std::atomic<uint32_t> cacheSize_;
ThreadLocalPtr<IntCache, Tag, AccessModeStrict> cache_;
struct IntCache {
ThreadCachedInt* parent_;
mutable std::atomic<IntT> val_;
mutable uint32_t numUpdates_;
std::atomic<bool> reset_;
explicit IntCache(ThreadCachedInt& parent)
: parent_(&parent), val_(0), numUpdates_(0), reset_(false) {
}
void increment(IntT inc) {
if ((__builtin_expect((!reset_.load(std::memory_order_acquire)),
1))) {
val_.store(val_.load(std::memory_order_relaxed) + inc,
std::memory_order_release);
} else {
val_.store(inc, std::memory_order_relaxed);
reset_.store(false, std::memory_order_release);
}
++numUpdates_;
if ((__builtin_expect(
(numUpdates_ >
parent_->cacheSize_.load(std::memory_order_acquire)),
0))
) {
flush();
}
}
void flush() const {
parent_->target_.fetch_add(val_, std::memory_order_release);
val_.store(0, std::memory_order_release);
numUpdates_ = 0;
}
~IntCache() {
flush();
}
};
};
} // namespace folly
// # 38 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 2 3 4
namespace folly {
struct AtomicHashArrayLinearProbeFcn {
inline size_t operator()(size_t idx, size_t, size_t capacity) const {
idx += 1;
return (__builtin_expect((idx < capacity), 1)) ? idx : (idx - capacity);
}
};
struct AtomicHashArrayQuadraticProbeFcn {
inline size_t operator()(size_t idx,
size_t numProbes,
size_t capacity) const {
idx += numProbes;
return (__builtin_expect((idx < capacity), 1)) ? idx : (idx - capacity);
}
};
namespace detail {
template <typename NotKeyT, typename KeyT>
inline void checkLegalKeyIfKeyTImpl(NotKeyT, KeyT, KeyT, KeyT) {
}
template <typename KeyT>
inline void checkLegalKeyIfKeyTImpl(KeyT key_in,
KeyT emptyKey,
KeyT lockedKey,
KeyT erasedKey) {
while (google::_Check_string* _result =
google::Check_NEImpl(google::GetReferenceableValue(key_in),
google::GetReferenceableValue(emptyKey),
"key_in"
" "
"!="
" "
"emptyKey"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray.h",
78,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(key_in),
google::GetReferenceableValue(lockedKey),
"key_in"
" "
"!="
" "
"lockedKey"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray.h",
79,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(key_in),
google::GetReferenceableValue(erasedKey),
"key_in"
" "
"!="
" "
"erasedKey"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray.h",
80,
google::CheckOpString(_result))
.stream();
}
} // namespace detail
template <class KeyT,
class ValueT,
class HashFcn = std::hash<KeyT>,
class EqualFcn = std::equal_to<KeyT>,
class Allocator = std::allocator<char>,
class ProbeFcn = AtomicHashArrayLinearProbeFcn,
class KeyConvertFcn = Identity>
class AtomicHashMap;
template <class KeyT,
class ValueT,
class HashFcn = std::hash<KeyT>,
class EqualFcn = std::equal_to<KeyT>,
class Allocator = std::allocator<char>,
class ProbeFcn = AtomicHashArrayLinearProbeFcn,
class KeyConvertFcn = Identity>
class AtomicHashArray {
static_assert(
(std::is_convertible<KeyT, int32_t>::value ||
std::is_convertible<KeyT, int64_t>::value ||
std::is_convertible<KeyT, const void*>::value),
"You are trying to use AtomicHashArray with disallowed key "
"types. You must use atomically compare-and-swappable integer "
"keys, or a different container class.");
public:
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef HashFcn hasher;
typedef EqualFcn key_equal;
typedef KeyConvertFcn key_convert;
typedef std::pair<const KeyT, ValueT> value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* pointer;
typedef const value_type* const_pointer;
const size_t capacity_;
const size_t maxEntries_;
const KeyT kEmptyKey_;
const KeyT kLockedKey_;
const KeyT kErasedKey_;
template <class ContT, class IterVal>
struct aha_iterator;
typedef aha_iterator<const AtomicHashArray, const value_type>
const_iterator;
typedef aha_iterator<AtomicHashArray, value_type> iterator;
static void destroy(AtomicHashArray*);
private:
const size_t kAnchorMask_;
struct Deleter {
void operator()(AtomicHashArray* ptr) {
AtomicHashArray::destroy(ptr);
}
};
public:
typedef std::unique_ptr<AtomicHashArray, Deleter> SmartPtr;
// # 174 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 3 4
struct Config {
KeyT emptyKey;
KeyT lockedKey;
KeyT erasedKey;
double maxLoadFactor;
double growthFactor;
uint32_t entryCountThreadCacheSize;
size_t capacity;
Config()
: emptyKey((KeyT)-1),
lockedKey((KeyT)-2),
erasedKey((KeyT)-3),
maxLoadFactor(0.8),
growthFactor(-1),
entryCountThreadCacheSize(1000),
capacity(0) {
}
};
static SmartPtr create(size_t maxSize, const Config& c = Config());
// # 214 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 3 4
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
iterator find(LookupKeyT k) {
return iterator(
this,
findInternal<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k).idx);
}
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
const_iterator find(LookupKeyT k) const {
return const_cast<AtomicHashArray*>(this)
->find<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k);
}
// # 243 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 3 4
std::pair<iterator, bool> insert(const value_type& r) {
return emplace(r.first, r.second);
}
std::pair<iterator, bool> insert(value_type&& r) {
return emplace(r.first, std::move(r.second));
}
// # 261 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 3 4
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal,
typename LookupKeyToKeyFcn = key_convert,
typename... ArgTs>
std::pair<iterator, bool> emplace(LookupKeyT key_in, ArgTs&&... vCtorArgs) {
SimpleRetT ret = insertInternal<LookupKeyT,
LookupHashFcn,
LookupEqualFcn,
LookupKeyToKeyFcn>(
key_in, std::forward<ArgTs>(vCtorArgs)...);
return std::make_pair(iterator(this, ret.idx), ret.success);
}
size_t erase(KeyT k);
void clear();
size_t size() const {
return numEntries_.readFull() -
numErases_.load(std::memory_order_relaxed);
}
bool empty() const {
return size() == 0;
}
iterator begin() {
iterator it(this, 0);
it.advancePastEmpty();
return it;
}
const_iterator begin() const {
const_iterator it(this, 0);
it.advancePastEmpty();
return it;
}
iterator end() {
return iterator(this, capacity_);
}
const_iterator end() const {
return const_iterator(this, capacity_);
}
iterator findAt(uint32_t idx) {
while (google::_Check_string* _result = google::Check_LTImpl(
google::GetReferenceableValue(idx),
google::GetReferenceableValue(capacity_),
"idx"
" "
"<"
" "
"capacity_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray.h",
315,
google::CheckOpString(_result))
.stream();
return iterator(this, idx);
}
const_iterator findAt(uint32_t idx) const {
return const_cast<AtomicHashArray*>(this)->findAt(idx);
}
iterator makeIter(size_t idx) {
return iterator(this, idx);
}
const_iterator makeIter(size_t idx) const {
return const_iterator(this, idx);
}
double maxLoadFactor() const {
return ((double)maxEntries_) / capacity_;
}
void setEntryCountThreadCacheSize(uint32_t newSize) {
numEntries_.setCacheSize(newSize);
numPendingEntries_.setCacheSize(newSize);
}
uint32_t getEntryCountThreadCacheSize() const {
return numEntries_.getCacheSize();
}
private:
friend class AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn>;
struct SimpleRetT {
size_t idx;
bool success;
SimpleRetT(size_t i, bool s) : idx(i), success(s) {
}
SimpleRetT() = default;
};
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal,
typename LookupKeyToKeyFcn = Identity,
typename... ArgTs>
SimpleRetT insertInternal(LookupKeyT key, ArgTs&&... vCtorArgs);
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
SimpleRetT findInternal(const LookupKeyT key);
template <typename MaybeKeyT>
void checkLegalKeyIfKey(MaybeKeyT key) {
detail::checkLegalKeyIfKeyTImpl(
key, kEmptyKey_, kLockedKey_, kErasedKey_);
}
static std::atomic<KeyT>* cellKeyPtr(const value_type& r) {
static_assert(
sizeof(std::atomic<KeyT>) == sizeof(KeyT),
"std::atomic is implemented in an unexpected way for AHM");
return const_cast<std::atomic<KeyT>*>(
reinterpret_cast<std::atomic<KeyT> const*>(&r.first));
}
static KeyT relaxedLoadKey(const value_type& r) {
return cellKeyPtr(r)->load(std::memory_order_relaxed);
}
static KeyT acquireLoadKey(const value_type& r) {
return cellKeyPtr(r)->load(std::memory_order_acquire);
}
ThreadCachedInt<uint64_t> numEntries_;
ThreadCachedInt<uint64_t> numPendingEntries_;
std::atomic<int64_t> isFull_;
std::atomic<int64_t> numErases_;
value_type cells_[0];
AtomicHashArray(size_t capacity,
KeyT emptyKey,
KeyT lockedKey,
KeyT erasedKey,
double maxLoadFactor,
uint32_t cacheSize);
AtomicHashArray(const AtomicHashArray&) = delete;
AtomicHashArray& operator=(const AtomicHashArray&) = delete;
~AtomicHashArray() = default;
inline void unlockCell(value_type* const cell, KeyT newKey) {
cellKeyPtr(*cell)->store(newKey, std::memory_order_release);
}
inline bool tryLockCell(value_type* const cell) {
KeyT expect = kEmptyKey_;
return cellKeyPtr(*cell)->compare_exchange_strong(
expect, kLockedKey_, std::memory_order_acq_rel);
}
template <class LookupKeyT = key_type, class LookupHashFcn = hasher>
inline size_t keyToAnchorIdx(const LookupKeyT k) const {
const size_t hashVal = LookupHashFcn()(k);
const size_t probe = hashVal & kAnchorMask_;
return (__builtin_expect((probe < capacity_), 1)) ? probe
: hashVal % capacity_;
}
};
} // namespace folly
// # 1 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 1 3 4
// # 23 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/AtomicHashUtils.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/AtomicHashUtils.h" 3 4
// # 26 "tlm/deps/folly.exploded/include/folly/detail/AtomicHashUtils.h" 3 4
namespace folly {
namespace detail {
template <typename Cond>
void atomic_hash_spin_wait(Cond condition) {
constexpr size_t kPauseLimit = 10000;
for (size_t i = 0; condition(); ++i) {
if (i < kPauseLimit) {
folly::asm_volatile_pause();
} else {
std::this_thread::yield();
}
}
}
} // namespace detail
} // namespace folly
// # 24 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 2 3 4
// # 1 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 1 3 4
// # 17 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 3 4
// # 49 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 3 4
namespace folly {
namespace detail {
// # 71 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 3 4
template <class D, class V, class Tag>
class IteratorFacade {
public:
using value_type = V;
using reference = value_type&;
using pointer = value_type*;
using difference_type = ssize_t;
using iterator_category = Tag;
bool operator==(D const& rhs) const {
return asDerivedConst().equal(rhs);
}
bool operator!=(D const& rhs) const {
return !operator==(rhs);
}
// # 96 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 3 4
template <class D2,
std::enable_if_t<!std::is_same<D, D2>::value, int> = 0,
std::enable_if_t<std::is_convertible<D, D2>::value, int> = 0>
bool operator==(D2 const& rhs) const {
return D2(asDerivedConst()) == rhs;
}
template <class D2>
bool operator!=(D2 const& rhs) const {
return !operator==(rhs);
}
V& operator*() const {
return asDerivedConst().dereference();
}
V* operator->() const {
return std::addressof(operator*());
}
D& operator++() {
asDerived().increment();
return asDerived();
}
D operator++(int) {
auto ret = asDerived();
asDerived().increment();
return ret;
}
D& operator--() {
asDerived().decrement();
return asDerived();
}
D operator--(int) {
auto ret = asDerived();
asDerived().decrement();
return ret;
}
private:
D& asDerived() {
return static_cast<D&>(*this);
}
D const& asDerivedConst() const {
return static_cast<D const&>(*this);
}
};
// # 158 "tlm/deps/folly.exploded/include/folly/detail/Iterators.h" 3 4
template <class D, class I, class V, class Tag>
class IteratorAdaptor : public IteratorFacade<D, V, Tag> {
public:
using Super = IteratorFacade<D, V, Tag>;
using value_type = typename Super::value_type;
using iterator_category = typename Super::iterator_category;
using reference = typename Super::reference;
using pointer = typename Super::pointer;
using difference_type = typename Super::difference_type;
explicit IteratorAdaptor(I base) : base_(base) {
}
void increment() {
++base_;
}
void decrement() {
--base_;
}
V& dereference() const {
return *base_;
}
bool equal(D const& rhs) const {
return base_ == rhs.base_;
}
I const& base() const {
return base_;
}
I& base() {
return base_;
}
private:
I base_;
};
} // namespace detail
} // namespace folly
// # 25 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 2 3 4
namespace folly {
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::AtomicHashArray(size_t capacity,
KeyT emptyKey,
KeyT lockedKey,
KeyT erasedKey,
double _maxLoadFactor,
uint32_t cacheSize)
: capacity_(capacity),
maxEntries_(size_t(_maxLoadFactor * capacity_ + 0.5)),
kEmptyKey_(emptyKey),
kLockedKey_(lockedKey),
kErasedKey_(erasedKey),
kAnchorMask_(nextPowTwo(capacity_) - 1),
numEntries_(0, cacheSize),
numPendingEntries_(0, cacheSize),
isFull_(0),
numErases_(0) {
if (capacity == 0) {
throw_exception<std::invalid_argument>("capacity");
}
}
// # 76 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 3 4
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
template <class LookupKeyT, class LookupHashFcn, class LookupEqualFcn>
typename AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SimpleRetT
AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::findInternal(const LookupKeyT key_in) {
checkLegalKeyIfKey<LookupKeyT>(key_in);
for (size_t idx = keyToAnchorIdx<LookupKeyT, LookupHashFcn>(key_in),
numProbes = 0;
;
idx = ProbeFcn()(idx, numProbes, capacity_)) {
const KeyT key = acquireLoadKey(cells_[idx]);
if ((__builtin_expect((LookupEqualFcn()(key, key_in)), 1))) {
return SimpleRetT(idx, true);
}
if ((__builtin_expect((key == kEmptyKey_), 0))) {
return SimpleRetT(capacity_, false);
}
++numProbes;
if ((__builtin_expect((numProbes >= capacity_), 0))) {
return SimpleRetT(capacity_, false);
}
}
}
// # 135 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 3 4
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
template <typename LookupKeyT,
typename LookupHashFcn,
typename LookupEqualFcn,
typename LookupKeyToKeyFcn,
typename... ArgTs>
typename AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SimpleRetT
AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::insertInternal(LookupKeyT key_in,
ArgTs&&... vCtorArgs) {
const short NO_NEW_INSERTS = 1;
const short NO_PENDING_INSERTS = 2;
checkLegalKeyIfKey<LookupKeyT>(key_in);
size_t idx = keyToAnchorIdx<LookupKeyT, LookupHashFcn>(key_in);
size_t numProbes = 0;
for (;;) {
while (google::_Check_string* _result = google::Check_LTImpl(
google::GetReferenceableValue(idx),
google::GetReferenceableValue(capacity_),
"idx"
" "
"<"
" "
"capacity_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/"
"AtomicHashArray-inl.h",
172,
google::CheckOpString(_result))
.stream();
value_type* cell = &cells_[idx];
if (relaxedLoadKey(*cell) == kEmptyKey_) {
++numPendingEntries_;
if (isFull_.load(std::memory_order_acquire)) {
--numPendingEntries_;
// # 189
// "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h"
// 3 4
detail::atomic_hash_spin_wait([&] {
return (isFull_.load(std::memory_order_acquire) !=
NO_PENDING_INSERTS) &&
(numPendingEntries_.readFull() != 0);
});
isFull_.store(NO_PENDING_INSERTS, std::memory_order_release);
if (relaxedLoadKey(*cell) == kEmptyKey_) {
return SimpleRetT(capacity_, false);
}
} else {
if (tryLockCell(cell)) {
KeyT key_new;
try {
key_new = LookupKeyToKeyFcn()(key_in);
typedef typename std::remove_const<LookupKeyT>::type
LookupKeyTNoConst;
constexpr bool kAlreadyChecked =
std::is_same<KeyT, LookupKeyTNoConst>::value;
if (!kAlreadyChecked) {
checkLegalKeyIfKey(key_new);
}
static_cast<void>(0),
!((__builtin_expect(
!(relaxedLoadKey(*cell) == kLockedKey_),
0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/"
"folly.exploded/"
"include/folly/"
"AtomicHashArray-inl."
"h",
216)
.stream()
<< "Check failed: "
"relaxedLoadKey(*"
"cell) == "
"kLockedKey_"
" ";
using mapped =
typename std::remove_const<mapped_type>::type;
new (const_cast<mapped*>(&cell->second))
ValueT(std::forward<ArgTs>(vCtorArgs)...);
unlockCell(cell, key_new);
} catch (...) {
unlockCell(cell, kEmptyKey_);
--numPendingEntries_;
throw;
}
static_cast<void>(0),
!((__builtin_expect(
!(relaxedLoadKey(*cell) == key_new ||
relaxedLoadKey(*cell) == kErasedKey_),
0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/"
"include/folly/"
"AtomicHashArray-inl.h",
233)
.stream()
<< "Check failed: "
"relaxedLoadKey(*cell)"
" == key_new || "
"relaxedLoadKey(*cell)"
" == kErasedKey_"
" "
;
--numPendingEntries_;
++numEntries_;
if (numEntries_.readFast() >= maxEntries_) {
isFull_.store(NO_NEW_INSERTS,
std::memory_order_relaxed);
}
return SimpleRetT(idx, true);
}
--numPendingEntries_;
}
}
static_cast<void>(0),
!((__builtin_expect(!(relaxedLoadKey(*cell) != kEmptyKey_), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashArray-inl.h",
246)
.stream()
<< "Check failed: "
"relaxedLoadKey(*cell) != "
"kEmptyKey_"
" ";
if (kLockedKey_ == acquireLoadKey(*cell)) {
detail::atomic_hash_spin_wait(
[&] { return kLockedKey_ == acquireLoadKey(*cell); });
}
const KeyT thisKey = acquireLoadKey(*cell);
if (LookupEqualFcn()(thisKey, key_in)) {
return SimpleRetT(idx, false);
} else if (thisKey == kEmptyKey_ || thisKey == kLockedKey_) {
continue;
}
++numProbes;
if ((__builtin_expect((numProbes >= capacity_), 0))) {
return SimpleRetT(capacity_, false);
}
idx = ProbeFcn()(idx, numProbes, capacity_);
}
}
// # 286 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 3 4
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
size_t AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::erase(KeyT key_in) {
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(key_in),
google::GetReferenceableValue(kEmptyKey_),
"key_in"
" "
"!="
" "
"kEmptyKey_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
302,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(key_in),
google::GetReferenceableValue(kLockedKey_),
"key_in"
" "
"!="
" "
"kLockedKey_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
303,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(key_in),
google::GetReferenceableValue(kErasedKey_),
"key_in"
" "
"!="
" "
"kErasedKey_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
304,
google::CheckOpString(_result))
.stream();
for (size_t idx = keyToAnchorIdx(key_in), numProbes = 0;;
idx = ProbeFcn()(idx, numProbes, capacity_)) {
while (google::_Check_string* _result = google::Check_LTImpl(
google::GetReferenceableValue(idx),
google::GetReferenceableValue(capacity_),
"idx"
" "
"<"
" "
"capacity_"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/"
"AtomicHashArray-inl.h",
308,
google::CheckOpString(_result))
.stream();
value_type* cell = &cells_[idx];
KeyT currentKey = acquireLoadKey(*cell);
if (currentKey == kEmptyKey_ || currentKey == kLockedKey_) {
return 0;
}
if (EqualFcn()(currentKey, key_in)) {
KeyT expect = currentKey;
if (cellKeyPtr(*cell)->compare_exchange_strong(expect,
kErasedKey_)) {
numErases_.fetch_add(1, std::memory_order_relaxed);
return 1;
}
return 0;
}
++numProbes;
if ((__builtin_expect((numProbes >= capacity_), 0))) {
return 0;
}
}
}
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
typename AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SmartPtr
AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::create(size_t maxSize, const Config& c) {
while (google::_Check_string* _result = google::Check_LEImpl(
google::GetReferenceableValue(c.maxLoadFactor),
google::GetReferenceableValue(1.0),
"c.maxLoadFactor"
" "
"<="
" "
"1.0"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
369,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_GTImpl(
google::GetReferenceableValue(c.maxLoadFactor),
google::GetReferenceableValue(0.0),
"c.maxLoadFactor"
" "
">"
" "
"0.0"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
370,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_NEImpl(
google::GetReferenceableValue(c.emptyKey),
google::GetReferenceableValue(c.lockedKey),
"c.emptyKey"
" "
"!="
" "
"c.lockedKey"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h",
371,
google::CheckOpString(_result))
.stream();
size_t capacity = size_t(maxSize / c.maxLoadFactor);
size_t sz = sizeof(AtomicHashArray) + sizeof(value_type) * capacity;
auto const mem = Allocator().allocate(sz);
try {
new (mem) AtomicHashArray(capacity,
c.emptyKey,
c.lockedKey,
c.erasedKey,
c.maxLoadFactor,
c.entryCountThreadCacheSize);
} catch (...) {
Allocator().deallocate(mem, sz);
throw;
}
SmartPtr map(static_cast<AtomicHashArray*>((void*)mem));
// # 403 "tlm/deps/folly.exploded/include/folly/AtomicHashArray-inl.h" 3 4
for (auto i = (true ? (0) : (map->capacity_));
::folly::detail::notThereYet(i, (map->capacity_));
++i) {
cellKeyPtr(map->cells_[i])
->store(map->kEmptyKey_, std::memory_order_relaxed);
}
return map;
}
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
void AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::destroy(AtomicHashArray* p) {
(static_cast<bool>(p) ? void(0)
: __assert_fail("p",
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashArray-inl.h",
426,
__extension__ __PRETTY_FUNCTION__));
size_t sz = sizeof(AtomicHashArray) + sizeof(value_type) * p->capacity_;
for (auto i = (true ? (0) : (p->capacity_));
::folly::detail::notThereYet(i, (p->capacity_));
++i) {
if (p->cells_[i].first != p->kEmptyKey_) {
p->cells_[i].~value_type();
}
}
p->~AtomicHashArray();
Allocator().deallocate((char*)p, sz);
}
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
void AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::clear() {
for (auto i = (true ? (0) : (capacity_));
::folly::detail::notThereYet(i, (capacity_));
++i) {
if (cells_[i].first != kEmptyKey_) {
cells_[i].~value_type();
*const_cast<KeyT*>(&cells_[i].first) = kEmptyKey_;
}
static_cast<void>(0),
!((__builtin_expect(!(cells_[i].first == kEmptyKey_), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashArray-inl.h",
462)
.stream()
<< "Check failed: "
"cells_[i].first == kEmptyKey_"
" ";
}
numEntries_.set(0);
numPendingEntries_.set(0);
isFull_.store(0, std::memory_order_relaxed);
numErases_.store(0, std::memory_order_relaxed);
}
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
template <class ContT, class IterVal>
struct AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::aha_iterator
: detail::IteratorFacade<aha_iterator<ContT, IterVal>,
IterVal,
std::forward_iterator_tag> {
explicit aha_iterator() : aha_(nullptr) {
}
template <class OtherContT, class OtherVal>
aha_iterator(
const aha_iterator<OtherContT, OtherVal>& o,
typename std::enable_if<
std::is_convertible<OtherVal*, IterVal*>::value>::type* =
nullptr)
: aha_(o.aha_), offset_(o.offset_) {
}
explicit aha_iterator(ContT* array, size_t offset)
: aha_(array), offset_(offset) {
}
uint32_t getIndex() const {
return offset_;
}
void advancePastEmpty() {
while (offset_ < aha_->capacity_ && !isValid()) {
++offset_;
}
}
private:
friend class AtomicHashArray;
friend class detail::
IteratorFacade<aha_iterator, IterVal, std::forward_iterator_tag>;
void increment() {
++offset_;
advancePastEmpty();
}
bool equal(const aha_iterator& o) const {
return aha_ == o.aha_ && offset_ == o.offset_;
}
IterVal& dereference() const {
return aha_->cells_[offset_];
}
bool isValid() const {
KeyT key = acquireLoadKey(aha_->cells_[offset_]);
return key != aha_->kEmptyKey_ && key != aha_->kLockedKey_ &&
key != aha_->kErasedKey_;
}
private:
ContT* aha_;
size_t offset_;
};
} // namespace folly
// # 449 "tlm/deps/folly.exploded/include/folly/AtomicHashArray.h" 2 3 4
// # 90 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 2 3 4
namespace folly {
// # 149 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
struct __attribute__((__visibility__("default"))) AtomicHashMapFullError
: std::runtime_error {
explicit AtomicHashMapFullError()
: std::runtime_error("AtomicHashMap is full") {
}
};
template <class KeyT,
class ValueT,
class HashFcn,
class EqualFcn,
class Allocator,
class ProbeFcn,
class KeyConvertFcn>
class AtomicHashMap {
typedef AtomicHashArray<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>
SubMap;
public:
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef std::pair<const KeyT, ValueT> value_type;
typedef HashFcn hasher;
typedef EqualFcn key_equal;
typedef KeyConvertFcn key_convert;
typedef value_type* pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
typedef typename SubMap::Config Config;
template <class ContT, class IterVal, class SubIt>
struct ahm_iterator;
typedef ahm_iterator<const AtomicHashMap,
const value_type,
typename SubMap::const_iterator>
const_iterator;
typedef ahm_iterator<AtomicHashMap, value_type, typename SubMap::iterator>
iterator;
public:
const float kGrowthFrac_;
explicit AtomicHashMap(size_t finalSizeEst, const Config& c = Config());
AtomicHashMap(const AtomicHashMap&) = delete;
AtomicHashMap& operator=(const AtomicHashMap&) = delete;
~AtomicHashMap() {
const unsigned int numMaps =
numMapsAllocated_.load(std::memory_order_relaxed);
for (auto i = (true ? (0) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
SubMap* thisMap = subMaps_[i].load(std::memory_order_relaxed);
static_cast<void>(0),
!((__builtin_expect(!(thisMap), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashMap.h",
214)
.stream()
<< "Check failed: "
"thisMap"
" ";
SubMap::destroy(thisMap);
}
}
key_equal key_eq() const {
return key_equal();
}
hasher hash_function() const {
return hasher();
}
// # 241 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
std::pair<iterator, bool> insert(const value_type& r) {
return emplace(r.first, r.second);
}
std::pair<iterator, bool> insert(key_type k, const mapped_type& v) {
return emplace(k, v);
}
std::pair<iterator, bool> insert(value_type&& r) {
return emplace(r.first, std::move(r.second));
}
std::pair<iterator, bool> insert(key_type k, mapped_type&& v) {
return emplace(k, std::move(v));
}
// # 265 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal,
typename LookupKeyToKeyFcn = key_convert,
typename... ArgTs>
std::pair<iterator, bool> emplace(LookupKeyT k, ArgTs&&... vCtorArg);
// # 289 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
iterator find(LookupKeyT k);
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
const_iterator find(LookupKeyT k) const;
// # 308 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
size_type erase(key_type k);
// # 318 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
void clear();
// # 328 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
size_t size() const;
bool empty() const {
return size() == 0;
}
size_type count(key_type k) const {
return find(k) == end() ? 0 : 1;
}
// # 347 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 3 4
iterator findAt(uint32_t idx) {
SimpleRetT ret = findAtInternal(idx);
while (google::_Check_string* _result = google::Check_LTImpl(
google::GetReferenceableValue(ret.i),
google::GetReferenceableValue(numSubMaps()),
"ret.i"
" "
"<"
" "
"numSubMaps()"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap.h",
349,
google::CheckOpString(_result))
.stream();
return iterator(this,
ret.i,
subMaps_[ret.i]
.load(std::memory_order_relaxed)
->makeIter(ret.j));
}
const_iterator findAt(uint32_t idx) const {
return const_cast<AtomicHashMap*>(this)->findAt(idx);
}
size_t capacity() const;
size_t spaceRemaining() const;
void setEntryCountThreadCacheSize(int32_t newSize) {
const int numMaps = numMapsAllocated_.load(std::memory_order_acquire);
for (int i = 0; i < numMaps; ++i) {
SubMap* map = subMaps_[i].load(std::memory_order_relaxed);
map->setEntryCountThreadCacheSize(newSize);
}
}
int numSubMaps() const {
return numMapsAllocated_.load(std::memory_order_acquire);
}
iterator begin() {
iterator it(
this, 0, subMaps_[0].load(std::memory_order_relaxed)->begin());
it.checkAdvanceToNextSubmap();
return it;
}
const_iterator begin() const {
const_iterator it(
this, 0, subMaps_[0].load(std::memory_order_relaxed)->begin());
it.checkAdvanceToNextSubmap();
return it;
}
iterator end() {
return iterator();
}
const_iterator end() const {
return const_iterator();
}
inline uint32_t recToIdx(const value_type& r, bool mayInsert = true) {
SimpleRetT ret = mayInsert ? insertInternal(r.first, r.second)
: findInternal(r.first);
return encodeIndex(ret.i, ret.j);
}
inline uint32_t recToIdx(value_type&& r, bool mayInsert = true) {
SimpleRetT ret = mayInsert
? insertInternal(r.first, std::move(r.second))
: findInternal(r.first);
return encodeIndex(ret.i, ret.j);
}
inline uint32_t recToIdx(key_type k,
const mapped_type& v,
bool mayInsert = true) {
SimpleRetT ret = mayInsert ? insertInternal(k, v) : findInternal(k);
return encodeIndex(ret.i, ret.j);
}
inline uint32_t recToIdx(key_type k,
mapped_type&& v,
bool mayInsert = true) {
SimpleRetT ret =
mayInsert ? insertInternal(k, std::move(v)) : findInternal(k);
return encodeIndex(ret.i, ret.j);
}
inline uint32_t keyToIdx(const KeyT k, bool mayInsert = false) {
return recToIdx(value_type(k), mayInsert);
}
inline const value_type& idxToRec(uint32_t idx) const {
SimpleRetT ret = findAtInternal(idx);
return subMaps_[ret.i].load(std::memory_order_relaxed)->idxToRec(ret.j);
}
private:
static const uint32_t kNumSubMapBits_ = 4;
static const uint32_t kSecondaryMapBit_ = 1u << 31;
static const uint32_t kSubMapIndexShift_ = 32 - kNumSubMapBits_ - 1;
static const uint32_t kSubMapIndexMask_ = (1 << kSubMapIndexShift_) - 1;
static const uint32_t kNumSubMaps_ = 1 << kNumSubMapBits_;
static const uintptr_t kLockedPtr_ = 0x88ULL << 48;
struct SimpleRetT {
uint32_t i;
size_t j;
bool success;
SimpleRetT(uint32_t ii, size_t jj, bool s) : i(ii), j(jj), success(s) {
}
SimpleRetT() = default;
};
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal,
typename LookupKeyToKeyFcn = key_convert,
typename... ArgTs>
SimpleRetT insertInternal(LookupKeyT key, ArgTs&&... value);
template <typename LookupKeyT = key_type,
typename LookupHashFcn = hasher,
typename LookupEqualFcn = key_equal>
SimpleRetT findInternal(const LookupKeyT k) const;
SimpleRetT findAtInternal(uint32_t idx) const;
std::atomic<SubMap*> subMaps_[kNumSubMaps_];
std::atomic<uint32_t> numMapsAllocated_;
inline bool tryLockMap(unsigned int idx) {
SubMap* val = nullptr;
return subMaps_[idx].compare_exchange_strong(
val, (SubMap*)kLockedPtr_, std::memory_order_acquire);
}
static inline uint32_t encodeIndex(uint32_t subMap, uint32_t subMapIdx);
};
template <class KeyT,
class ValueT,
class HashFcn = std::hash<KeyT>,
class EqualFcn = std::equal_to<KeyT>,
class Allocator = std::allocator<char>>
using QuadraticProbingAtomicHashMap =
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
AtomicHashArrayQuadraticProbeFcn>;
} // namespace folly
// # 1 "tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h" 1 3 4
// # 26 "tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h" 3 4
namespace folly {
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::AtomicHashMap(size_t finalSizeEst,
const Config& config)
: kGrowthFrac_(config.growthFactor < 0 ? 1.0f - config.maxLoadFactor
: config.growthFactor) {
static_cast<void>(0),
!((__builtin_expect(!(config.maxLoadFactor > 0.0f &&
config.maxLoadFactor < 1.0f),
0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/"
"AtomicHashMap-inl.h",
49)
.stream()
<< "Check failed: "
"config.maxLoadFactor > 0.0f && "
"config.maxLoadFactor < 1.0f"
" ";
subMaps_[0].store(SubMap::create(finalSizeEst, config).release(),
std::memory_order_relaxed);
auto subMapCount = kNumSubMaps_;
for (auto i = (true ? (1) : (subMapCount));
::folly::detail::notThereYet(i, (subMapCount));
++i) {
subMaps_[i].store(nullptr, std::memory_order_relaxed);
}
numMapsAllocated_.store(1, std::memory_order_relaxed);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <typename LookupKeyT,
typename LookupHashFcn,
typename LookupEqualFcn,
typename LookupKeyToKeyFcn,
typename... ArgTs>
std::pair<typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::iterator,
bool>
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::emplace(LookupKeyT k, ArgTs&&... vCtorArgs) {
SimpleRetT ret = insertInternal<LookupKeyT,
LookupHashFcn,
LookupEqualFcn,
LookupKeyToKeyFcn>(
k, std::forward<ArgTs>(vCtorArgs)...);
SubMap* subMap = subMaps_[ret.i].load(std::memory_order_relaxed);
return std::make_pair(iterator(this, ret.i, subMap->makeIter(ret.j)),
ret.success);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <typename LookupKeyT,
typename LookupHashFcn,
typename LookupEqualFcn,
typename LookupKeyToKeyFcn,
typename... ArgTs>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SimpleRetT
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::insertInternal(LookupKeyT key,
ArgTs&&... vCtorArgs) {
beginInsertInternal:
auto nextMapIdx = numMapsAllocated_.load(std::memory_order_acquire);
typename SubMap::SimpleRetT ret;
for (auto i = (true ? (0) : (nextMapIdx));
::folly::detail::notThereYet(i, (nextMapIdx));
++i) {
SubMap* subMap = subMaps_[i].load(std::memory_order_relaxed);
ret = subMap->template insertInternal<LookupKeyT,
LookupHashFcn,
LookupEqualFcn,
LookupKeyToKeyFcn>(
key, std::forward<ArgTs>(vCtorArgs)...);
if (ret.idx == subMap->capacity_) {
continue;
}
return SimpleRetT(i, ret.idx, ret.success);
}
SubMap* primarySubMap = subMaps_[0].load(std::memory_order_relaxed);
if (nextMapIdx >= kNumSubMaps_ ||
primarySubMap->capacity_ * kGrowthFrac_ < 1.0) {
throw AtomicHashMapFullError();
}
if (tryLockMap(nextMapIdx)) {
size_t numCellsAllocated =
(size_t)(primarySubMap->capacity_ *
std::pow(1.0 + kGrowthFrac_, nextMapIdx - 1));
size_t newSize = size_t(numCellsAllocated * kGrowthFrac_);
static_cast<void>(0),
!((__builtin_expect(!(subMaps_[nextMapIdx].load(
std::memory_order_relaxed) ==
(SubMap*)kLockedPtr_),
0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashMap-inl.h",
170)
.stream()
<< "Check failed: "
"subMaps_[nextMapIdx].load(std::"
"memory_order_relaxed) == "
"(SubMap*)kLockedPtr_"
" "
;
Config config;
config.emptyKey = primarySubMap->kEmptyKey_;
config.lockedKey = primarySubMap->kLockedKey_;
config.erasedKey = primarySubMap->kErasedKey_;
config.maxLoadFactor = primarySubMap->maxLoadFactor();
config.entryCountThreadCacheSize =
primarySubMap->getEntryCountThreadCacheSize();
subMaps_[nextMapIdx].store(SubMap::create(newSize, config).release(),
std::memory_order_relaxed);
numMapsAllocated_.fetch_add(1, std::memory_order_release);
while (google::_Check_string* _result = google::Check_EQImpl(
google::GetReferenceableValue(nextMapIdx + 1),
google::GetReferenceableValue(numMapsAllocated_.load(
std::memory_order_relaxed)),
"nextMapIdx + 1"
" "
"=="
" "
"numMapsAllocated_.load(std::memory_order_relaxed)"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h",
187,
google::CheckOpString(_result))
.stream();
} else {
detail::atomic_hash_spin_wait([&] {
return nextMapIdx >=
numMapsAllocated_.load(std::memory_order_acquire);
});
}
SubMap* loadedMap = subMaps_[nextMapIdx].load(std::memory_order_relaxed);
static_cast<void>(0),
!((__builtin_expect(
!(loadedMap && loadedMap != (SubMap*)kLockedPtr_), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/"
"AtomicHashMap-inl.h",
200)
.stream()
<< "Check failed: "
"loadedMap && loadedMap != "
"(SubMap*)kLockedPtr_"
" ";
ret = loadedMap->insertInternal(key, std::forward<ArgTs>(vCtorArgs)...);
if (ret.idx != loadedMap->capacity_) {
return SimpleRetT(nextMapIdx, ret.idx, ret.success);
}
goto beginInsertInternal;
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <class LookupKeyT, class LookupHashFcn, class LookupEqualFcn>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::iterator
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::find(LookupKeyT k) {
SimpleRetT ret = findInternal<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k);
if (!ret.success) {
return end();
}
SubMap* subMap = subMaps_[ret.i].load(std::memory_order_relaxed);
return iterator(this, ret.i, subMap->makeIter(ret.j));
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <class LookupKeyT, class LookupHashFcn, class LookupEqualFcn>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::const_iterator
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::find(LookupKeyT k) const {
return const_cast<AtomicHashMap*>(this)
->find<LookupKeyT, LookupHashFcn, LookupEqualFcn>(k);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <class LookupKeyT, class LookupHashFcn, class LookupEqualFcn>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SimpleRetT
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::findInternal(const LookupKeyT k) const {
SubMap* const primaryMap = subMaps_[0].load(std::memory_order_relaxed);
typename SubMap::SimpleRetT ret =
primaryMap->template findInternal<LookupKeyT,
LookupHashFcn,
LookupEqualFcn>(k);
if ((__builtin_expect((ret.idx != primaryMap->capacity_), 1))) {
return SimpleRetT(0, ret.idx, ret.success);
}
const unsigned int numMaps =
numMapsAllocated_.load(std::memory_order_acquire);
for (auto i = (true ? (1) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
SubMap* thisMap = subMaps_[i].load(std::memory_order_relaxed);
ret = thisMap->template findInternal<LookupKeyT,
LookupHashFcn,
LookupEqualFcn>(k);
if ((__builtin_expect((ret.idx != thisMap->capacity_), 1))) {
return SimpleRetT(i, ret.idx, ret.success);
}
}
return SimpleRetT(numMaps, 0, false);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::SimpleRetT
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::findAtInternal(uint32_t idx) const {
uint32_t subMapIdx, subMapOffset;
if (idx & kSecondaryMapBit_) {
idx &= ~kSecondaryMapBit_;
subMapIdx = idx >> kSubMapIndexShift_;
while (google::_Check_string* _result = google::Check_LTImpl(
google::GetReferenceableValue(subMapIdx),
google::GetReferenceableValue(numMapsAllocated_.load(
std::memory_order_relaxed)),
"subMapIdx"
" "
"<"
" "
"numMapsAllocated_.load(std::memory_order_relaxed)"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h",
353,
google::CheckOpString(_result))
.stream();
subMapOffset = idx & kSubMapIndexMask_;
} else {
subMapIdx = 0;
subMapOffset = idx;
}
return SimpleRetT(subMapIdx, subMapOffset, true);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
typename AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::size_type
AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::erase(const KeyT k) {
int const numMaps = numMapsAllocated_.load(std::memory_order_acquire);
for (auto i = (true ? (0) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
if (subMaps_[i].load(std::memory_order_relaxed)->erase(k)) {
return 1;
}
}
return 0;
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
size_t AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::capacity() const {
size_t totalCap(0);
int const numMaps = numMapsAllocated_.load(std::memory_order_acquire);
for (auto i = (true ? (0) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
totalCap += subMaps_[i].load(std::memory_order_relaxed)->capacity_;
}
return totalCap;
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
size_t AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::spaceRemaining() const {
size_t spaceRem(0);
int const numMaps = numMapsAllocated_.load(std::memory_order_acquire);
for (auto i = (true ? (0) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
SubMap* thisMap = subMaps_[i].load(std::memory_order_relaxed);
spaceRem += std::max(
0, thisMap->maxEntries_ - &thisMap->numEntries_.readFull());
}
return spaceRem;
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
void AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::clear() {
subMaps_[0].load(std::memory_order_relaxed)->clear();
int const numMaps = numMapsAllocated_.load(std::memory_order_relaxed);
for (auto i = (true ? (1) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
SubMap* thisMap = subMaps_[i].load(std::memory_order_relaxed);
static_cast<void>(0),
!((__builtin_expect(!(thisMap), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashMap-inl.h",
474)
.stream()
<< "Check failed: "
"thisMap"
" ";
SubMap::destroy(thisMap);
subMaps_[i].store(nullptr, std::memory_order_relaxed);
}
numMapsAllocated_.store(1, std::memory_order_relaxed);
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
size_t AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::size() const {
size_t totalSize(0);
int const numMaps = numMapsAllocated_.load(std::memory_order_acquire);
for (auto i = (true ? (0) : (numMaps));
::folly::detail::notThereYet(i, (numMaps));
++i) {
totalSize += subMaps_[i].load(std::memory_order_relaxed)->size();
}
return totalSize;
}
// # 524 "tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h" 3 4
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
inline uint32_t AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::encodeIndex(uint32_t subMap,
uint32_t offset) {
while (google::_Check_string* _result = google::Check_EQImpl(
google::GetReferenceableValue(offset & kSecondaryMapBit_),
google::GetReferenceableValue(0),
"offset & kSecondaryMapBit_"
" "
"=="
" "
"0"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h",
540,
google::CheckOpString(_result))
.stream();
if (subMap == 0) {
return offset;
}
while (google::_Check_string* _result = google::Check_EQImpl(
google::GetReferenceableValue(subMap >> kNumSubMapBits_),
google::GetReferenceableValue(0),
"subMap >> kNumSubMapBits_"
" "
"=="
" "
"0"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h",
545,
google::CheckOpString(_result))
.stream();
while (google::_Check_string* _result = google::Check_EQImpl(
google::GetReferenceableValue(
offset & (~kSubMapIndexMask_ | kSecondaryMapBit_)),
google::GetReferenceableValue(0),
"offset & (~kSubMapIndexMask_ | kSecondaryMapBit_)"
" "
"=="
" "
"0"))
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/folly/AtomicHashMap-inl.h",
547,
google::CheckOpString(_result))
.stream();
return offset | (subMap << kSubMapIndexShift_) | kSecondaryMapBit_;
}
template <typename KeyT,
typename ValueT,
typename HashFcn,
typename EqualFcn,
typename Allocator,
typename ProbeFcn,
typename KeyConvertFcn>
template <class ContT, class IterVal, class SubIt>
struct AtomicHashMap<KeyT,
ValueT,
HashFcn,
EqualFcn,
Allocator,
ProbeFcn,
KeyConvertFcn>::ahm_iterator
: detail::IteratorFacade<ahm_iterator<ContT, IterVal, SubIt>,
IterVal,
std::forward_iterator_tag> {
explicit ahm_iterator() : ahm_(nullptr) {
}
template <class OtherContT, class OtherVal, class OtherSubIt>
ahm_iterator(const ahm_iterator<OtherContT, OtherVal, OtherSubIt>& o,
typename std::enable_if<
std::is_convertible<OtherSubIt, SubIt>::value>::type* =
nullptr)
: ahm_(o.ahm_), subMap_(o.subMap_), subIt_(o.subIt_) {
}
uint32_t getIndex() const {
static_cast<void>(0),
!((__builtin_expect(!(!isEnd()), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashMap-inl.h",
593)
.stream()
<< "Check failed: "
"!isEnd()"
" ";
return ahm_->encodeIndex(subMap_, subIt_.getIndex());
}
private:
friend class AtomicHashMap;
explicit ahm_iterator(ContT* ahm, uint32_t subMap, const SubIt& subIt)
: ahm_(ahm), subMap_(subMap), subIt_(subIt) {
}
friend class detail::
IteratorFacade<ahm_iterator, IterVal, std::forward_iterator_tag>;
void increment() {
static_cast<void>(0),
!((__builtin_expect(!(!isEnd()), 0)))
? (void)0
: google::LogMessageVoidify() &
google::LogMessageFatal(
"tlm/deps/folly.exploded/include/"
"folly/AtomicHashMap-inl.h",
606)
.stream()
<< "Check failed: "
"!isEnd()"
" ";
++subIt_;
checkAdvanceToNextSubmap();
}
bool equal(const ahm_iterator& other) const {
if (ahm_ != other.ahm_) {
return false;
}
if (isEnd() || other.isEnd()) {
return isEnd() == other.isEnd();
}
return subMap_ == other.subMap_ && subIt_ == other.subIt_;
}
IterVal& dereference() const {
return *subIt_;
}
bool isEnd() const {
return ahm_ == nullptr;
}
void checkAdvanceToNextSubmap() {
if (isEnd()) {
return;
}
SubMap* thisMap =
ahm_->subMaps_[subMap_].load(std::memory_order_relaxed);
while (subIt_ == thisMap->end()) {
if (subMap_ + 1 <
ahm_->numMapsAllocated_.load(std::memory_order_acquire)) {
++subMap_;
thisMap =
ahm_->subMaps_[subMap_].load(std::memory_order_relaxed);
subIt_ = thisMap->begin();
} else {
ahm_ = nullptr;
return;
}
}
}
private:
ContT* ahm_;
uint32_t subMap_;
SubIt subIt_;
};
} // namespace folly
// # 501 "tlm/deps/folly.exploded/include/folly/AtomicHashMap.h" 2 3 4
// # 19 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc" 2
// # 20 "/mnt/Code/couchbase/docker/kv_engine/engines/ep/src/dcp/producer.cc"
void DcpProducer::bufferAcknowledgement(uint32_t opaque, Vbid vbucket) {
logger->warn("{}", vbucket);
}
void makeStreamsMap(size_t maxNumVBuckets) {
auto p = folly::AtomicHashArray<char, char>::create(maxNumVBuckets);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment