Add float and double parsing

This commit is contained in:
Lukas Joswiak 2021-02-17 16:04:23 -08:00
parent f1415412f1
commit 9e20b08976
3 changed files with 74 additions and 3 deletions

View File

@ -40,7 +40,7 @@ GlobalConfig& GlobalConfig::globalConfig() {
const std::any GlobalConfig::get(StringRef name) { const std::any GlobalConfig::get(StringRef name) {
auto it = data.find(name); auto it = data.find(name);
if (it == data.end()) { if (it == data.end()) {
return nullptr; return std::any{};
} }
return it->second; return it->second;
} }
@ -51,10 +51,15 @@ Future<Void> GlobalConfig::onInitialized() {
void GlobalConfig::insert(KeyRef key, ValueRef value) { void GlobalConfig::insert(KeyRef key, ValueRef value) {
Tuple t = Tuple::unpack(value); Tuple t = Tuple::unpack(value);
// TODO: Add more Tuple types
if (t.getType(0) == Tuple::ElementType::UTF8) { if (t.getType(0) == Tuple::ElementType::UTF8) {
data[key] = t.getString(0); data[key] = t.getString(0);
} else if (t.getType(0) == Tuple::ElementType::INT) { } else if (t.getType(0) == Tuple::ElementType::INT) {
data[key] = t.getInt(0); data[key] = t.getInt(0);
} else if (t.getType(0) == Tuple::ElementType::FLOAT) {
data[key] = t.getFloat(0);
} else if (t.getType(0) == Tuple::ElementType::DOUBLE) {
data[key] = t.getDouble(0);
} else {
ASSERT(false);
} }
} }

View File

@ -20,6 +20,18 @@
#include "fdbclient/Tuple.h" #include "fdbclient/Tuple.h"
static float bigEndianFloat(float orig) {
int32_t big = *(int32_t*)&orig;
big = bigEndian32(big);
return *(float*)&big;
}
static double bigEndianDouble(double orig) {
int64_t big = *(int64_t*)&orig;
big = bigEndian64(big);
return *(double*)&big;
}
static size_t find_string_terminator(const StringRef data, size_t offset) { static size_t find_string_terminator(const StringRef data, size_t offset) {
size_t i = offset; size_t i = offset;
while (i < data.size() - 1 && !(data[i] == '\x00' && data[i + 1] != (uint8_t)'\xff')) { while (i < data.size() - 1 && !(data[i] == '\x00' && data[i + 1] != (uint8_t)'\xff')) {
@ -29,6 +41,19 @@ static size_t find_string_terminator(const StringRef data, size_t offset) {
return i; return i;
} }
// If encoding and the sign bit is 1 (the number is negative), flip all the bits.
// If decoding and the sign bit is 0 (the number is negative), flip all the bits.
// Otherwise, the number is positive, so flip the sign bit.
static void adjust_floating_point(uint8_t *bytes, size_t size, bool encode) {
if((encode && ((uint8_t)(bytes[0] & 0x80) != (uint8_t)0x00)) || (!encode && ((uint8_t)(bytes[0] & 0x80) != (uint8_t)0x80))) {
for(size_t i = 0; i < size; i++) {
bytes[i] ^= (uint8_t)0xff;
}
} else {
bytes[0] ^= (uint8_t)0x80;
}
}
Tuple::Tuple(StringRef const& str, bool exclude_incomplete) { Tuple::Tuple(StringRef const& str, bool exclude_incomplete) {
data.append(data.arena(), str.begin(), str.size()); data.append(data.arena(), str.begin(), str.size());
@ -228,6 +253,45 @@ int64_t Tuple::getInt(size_t index, bool allow_incomplete) const {
return swap; return swap;
} }
// TODO: Combine with bindings/flow/Tuple.*. This code is copied from there.
float Tuple::getFloat(size_t index) const {
if(index >= offsets.size()) {
throw invalid_tuple_index();
}
ASSERT_LT(offsets[index], data.size());
uint8_t code = data[offsets[index]];
if(code != 0x20) {
throw invalid_tuple_data_type();
}
float swap;
uint8_t* bytes = (uint8_t*)&swap;
ASSERT_LE(offsets[index] + 1 + sizeof(float), data.size());
swap = *(float*)(data.begin() + offsets[index] + 1);
adjust_floating_point( bytes, sizeof(float), false );
return bigEndianFloat(swap);
}
double Tuple::getDouble(size_t index) const {
if(index >= offsets.size()) {
throw invalid_tuple_index();
}
ASSERT_LT(offsets[index], data.size());
uint8_t code = data[offsets[index]];
if(code != 0x21) {
throw invalid_tuple_data_type();
}
double swap;
uint8_t* bytes = (uint8_t*)&swap;
ASSERT_LE(offsets[index] + 1 + sizeof(double), data.size());
swap = *(double*)(data.begin() + offsets[index] + 1);
adjust_floating_point( bytes, sizeof(double), false );
return bigEndianDouble(swap);
}
KeyRange Tuple::range(Tuple const& tuple) const { KeyRange Tuple::range(Tuple const& tuple) const {
VectorRef<uint8_t> begin; VectorRef<uint8_t> begin;
VectorRef<uint8_t> end; VectorRef<uint8_t> end;

View File

@ -47,7 +47,7 @@ struct Tuple {
return append(t); return append(t);
} }
enum ElementType { NULL_TYPE, INT, BYTES, UTF8 }; enum ElementType { NULL_TYPE, INT, BYTES, UTF8, FLOAT, DOUBLE };
// this is number of elements, not length of data // this is number of elements, not length of data
size_t size() const { return offsets.size(); } size_t size() const { return offsets.size(); }
@ -55,6 +55,8 @@ struct Tuple {
ElementType getType(size_t index) const; ElementType getType(size_t index) const;
Standalone<StringRef> getString(size_t index) const; Standalone<StringRef> getString(size_t index) const;
int64_t getInt(size_t index, bool allow_incomplete = false) const; int64_t getInt(size_t index, bool allow_incomplete = false) const;
float getFloat(size_t index) const;
double getDouble(size_t index) const;
KeyRange range(Tuple const& tuple = Tuple()) const; KeyRange range(Tuple const& tuple = Tuple()) const;