1#include <fcb/generated/header_generated.h>
17template <
typename T>
void put_le(std::vector<std::uint8_t>& out, T value) {
18 static_assert(std::is_integral<T>::value,
"integral only");
19 using U =
typename std::make_unsigned<T>::type;
20 U u =
static_cast<U
>(value);
21 for (std::size_t i = 0; i <
sizeof(T); ++i) {
22 out.push_back(
static_cast<std::uint8_t
>((u >> (8 * i)) & 0xFF));
26template <
typename T> T get_le(
bytes_view b, std::size_t at = 0) {
27 using U =
typename std::make_unsigned<T>::type;
29 for (std::size_t i = 0; i <
sizeof(T); ++i) {
30 u |=
static_cast<U
>(b[at + i]) << (8 * i);
32 return static_cast<T
>(u);
37int cmp_ordered_double(
double a,
double b) {
38 const bool na = std::isnan(a);
39 const bool nb = std::isnan(b);
53void require_size(
bytes_view b, std::size_t need,
const char* what) {
54 if (b.size() < need) {
90#define FCB_KV_INT(NAME, TYPE, KIND, FIELD) \
91 KeyValue KeyValue::NAME(TYPE v) { \
93 k.kind_ = KeyKind::KIND; \
94 k.FIELD = static_cast<decltype(k.FIELD)>(v); \
111 k.f_ =
static_cast<double>(v);
138 if (!is_string_kind(
kind)) {
148 std::vector<std::uint8_t> out;
154 put_le<std::int8_t>(out,
static_cast<std::int8_t
>(v.i_));
157 put_le<std::uint8_t>(out,
static_cast<std::uint8_t
>(v.u_));
160 put_le<std::int16_t>(out,
static_cast<std::int16_t
>(v.i_));
163 put_le<std::uint16_t>(out,
static_cast<std::uint16_t
>(v.u_));
166 put_le<std::int32_t>(out,
static_cast<std::int32_t
>(v.i_));
169 put_le<std::uint32_t>(out,
static_cast<std::uint32_t
>(v.u_));
172 put_le<std::int64_t>(out, v.i_);
175 put_le<std::uint64_t>(out, v.u_);
178 out.push_back(v.u_ != 0 ? 1 : 0);
186 const float f =
static_cast<float>(v.f_);
188 std::memcpy(&bits, &f,
sizeof(bits));
189 put_le<std::uint32_t>(out, bits);
194 std::memcpy(&bits, &v.f_,
sizeof(bits));
195 put_le<std::uint64_t>(out, bits);
199 put_le<std::int64_t>(out, v.i_);
200 put_le<std::uint32_t>(out,
static_cast<std::uint32_t
>(v.u_));
211 const std::size_t take = std::min(v.str_.size(), n);
212 std::memcpy(out.data(), v.str_.data(), take);
221 require_size(b, n,
"decode_key");
244 const std::uint32_t bits = get_le<std::uint32_t>(b);
246 std::memcpy(&f, &bits,
sizeof(f));
250 const std::uint64_t bits = get_le<std::uint64_t>(b);
252 std::memcpy(&d, &bits,
sizeof(d));
263 while (len < n && b[len] != 0)
266 std::string(
reinterpret_cast<const char*
>(b.
data()), len));
273 if (a.kind_ != b.kind_) {
281 return a.i_ < b.i_ ? -1 : (a.i_ > b.i_ ? 1 : 0);
288 return a.u_ < b.u_ ? -1 : (a.u_ > b.u_ ? 1 : 0);
292 return cmp_ordered_double(a.f_, b.f_);
296 return a.i_ < b.i_ ? -1 : 1;
297 return a.u_ < b.u_ ? -1 : (a.u_ > b.u_ ? 1 : 0);
306 const int c = std::memcmp(ea.data(), eb.data(), ea.size());
307 return c < 0 ? -1 : (c > 0 ? 1 : 0);
388 switch (
static_cast<::ColumnType
>(column_type)) {
396 case ::ColumnType::Byte:
398 case ::ColumnType::UByte:
400 case ::ColumnType::Bool:
402 case ::ColumnType::Short:
404 case ::ColumnType::UShort:
406 case ::ColumnType::Int:
408 case ::ColumnType::UInt:
410 case ::ColumnType::Long:
412 case ::ColumnType::ULong:
414 case ::ColumnType::Float:
416 case ::ColumnType::Double:
418 case ::ColumnType::String:
420 case ::ColumnType::DateTime:
422 case ::ColumnType::Json:
424 case ::ColumnType::Binary:
Every failure the library reports is one of these.
static KeyValue from_datetime(std::int64_t seconds, std::uint32_t nanos)
static KeyValue from_i64(std::int64_t v)
static KeyValue from_i8(std::int8_t v)
static KeyValue from_u32(std::uint32_t v)
static KeyValue from_i16(std::int16_t v)
static KeyValue from_f32(float v)
static KeyValue from_i32(std::int32_t v)
static KeyValue from_u16(std::uint16_t v)
static KeyValue from_u8(std::uint8_t v)
static KeyValue from_f64(double v)
static KeyValue from_string(KeyKind kind, const std::string &v)
static KeyValue from_u64(std::uint64_t v)
static KeyValue from_bool(bool v)
Minimal C++17 stand-in for std::span: a non-owning view over contiguous memory.
T * data() const noexcept
#define FCB_KV_INT(NAME, TYPE, KIND, FIELD)
span< const std::uint8_t > bytes_view
The workhorse alias: a read-only view over bytes.
std::vector< std::uint8_t > encode_key(const KeyValue &v)
KeyKind key_kind_for_column(std::uint8_t column_type)
Column type to key kind, following what the WRITER emits.
KeyValue key_max(KeyKind kind)
int compare_keys(const KeyValue &a, const KeyValue &b)
Three-way comparison.
KeyKind
The concrete key types the B+tree index can hold.
std::size_t key_serialized_size(KeyKind kind)
Serialized width in bytes. DateTime is 12: i64 seconds + u32 nanos.
KeyValue decode_key(KeyKind kind, bytes_view b)
KeyValue key_min(KeyKind kind)
Sentinels used to lower open-ended range queries.