diff options
Diffstat (limited to 'ext/librethinkdbxx/src/datum.cc')
-rw-r--r-- | ext/librethinkdbxx/src/datum.cc | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/ext/librethinkdbxx/src/datum.cc b/ext/librethinkdbxx/src/datum.cc deleted file mode 100644 index e4dbc8dc..00000000 --- a/ext/librethinkdbxx/src/datum.cc +++ /dev/null @@ -1,449 +0,0 @@ -#include <float.h> -#include <cmath> - -#include "datum.h" -#include "json_p.h" -#include "utils.h" -#include "cursor.h" - -#include "rapidjson-config.h" -#include "rapidjson/prettywriter.h" -#include "rapidjson/stringbuffer.h" - -namespace RethinkDB { - -using TT = Protocol::Term::TermType; - -bool Datum::is_nil() const { - return type == Type::NIL; -} - -bool Datum::is_boolean() const { - return type == Type::BOOLEAN; -} - -bool Datum::is_number() const { - return type == Type::NUMBER; -} - -bool Datum::is_string() const { - return type == Type::STRING; -} - -bool Datum::is_object() const { - return type == Type::OBJECT; -} - -bool Datum::is_array() const { - return type == Type::ARRAY; -} - -bool Datum::is_binary() const { - return type == Type::BINARY; -} - -bool Datum::is_time() const { - return type == Type::TIME; -} - -bool* Datum::get_boolean() { - if (type == Type::BOOLEAN) { - return &value.boolean; - } else { - return NULL; - } -} - -const bool* Datum::get_boolean() const { - if (type == Type::BOOLEAN) { - return &value.boolean; - } else { - return NULL; - } -} - -double* Datum::get_number() { - if (type == Type::NUMBER) { - return &value.number; - } else { - return NULL; - } -} - -const double* Datum::get_number() const { - if (type == Type::NUMBER) { - return &value.number; - } else { - return NULL; - } -} - -std::string* Datum::get_string() { - if (type == Type::STRING) { - return &value.string; - } else { - return NULL; - } -} - -const std::string* Datum::get_string() const { - if (type == Type::STRING) { - return &value.string; - } else { - return NULL; - } -} - -Datum* Datum::get_field(std::string key) { - if (type != Type::OBJECT) { - return NULL; - } - auto it = value.object.find(key); - if (it == value.object.end()) { - return NULL; - } - return &it->second; -} - -const Datum* Datum::get_field(std::string key) const { - if (type != Type::OBJECT) { - return NULL; - } - auto it = value.object.find(key); - if (it == value.object.end()) { - return NULL; - } - return &it->second; -} - -Datum* Datum::get_nth(size_t i) { - if (type != Type::ARRAY) { - return NULL; - } - if (i >= value.array.size()) { - return NULL; - } - return &value.array[i]; -} - -const Datum* Datum::get_nth(size_t i) const { - if (type != Type::ARRAY) { - return NULL; - } - if (i >= value.array.size()) { - return NULL; - } - return &value.array[i]; -} - -Object* Datum::get_object() { - if (type == Type::OBJECT) { - return &value.object; - } else { - return NULL; - } -} - -const Object* Datum::get_object() const { - if (type == Type::OBJECT) { - return &value.object; - } else { - return NULL; - } -} - -Array* Datum::get_array() { - if (type == Type::ARRAY) { - return &value.array; - } else { - return NULL; - } -} - -const Array* Datum::get_array() const { - if (type == Type::ARRAY) { - return &value.array; - } else { - return NULL; - } -} - -Binary* Datum::get_binary() { - if (type == Type::BINARY) { - return &value.binary; - } else { - return NULL; - } -} - -const Binary* Datum::get_binary() const { - if (type == Type::BINARY) { - return &value.binary; - } else { - return NULL; - } -} - -Time* Datum::get_time() { - if (type == Type::TIME) { - return &value.time; - } else { - return NULL; - } -} - -const Time* Datum::get_time() const { - if (type == Type::TIME) { - return &value.time; - } else { - return NULL; - } -} - -bool& Datum::extract_boolean() { - if (type != Type::BOOLEAN) { - throw Error("extract_bool: Not a boolean"); - } - return value.boolean; -} - -double& Datum::extract_number() { - if (type != Type::NUMBER) { - throw Error("extract_number: Not a number: %s", write_datum(*this).c_str()); - } - return value.number; -} - -std::string& Datum::extract_string() { - if (type != Type::STRING) { - throw Error("extract_string: Not a string"); - } - return value.string; -} - -Object& Datum::extract_object() { - if (type != Type::OBJECT) { - throw Error("extract_object: Not an object"); - } - return value.object; -} - -Datum& Datum::extract_field(std::string key) { - if (type != Type::OBJECT) { - throw Error("extract_field: Not an object"); - } - auto it = value.object.find(key); - if (it == value.object.end()) { - throw Error("extract_field: No such key in object"); - } - return it->second; -} - -Datum& Datum::extract_nth(size_t i) { - if (type != Type::ARRAY) { - throw Error("extract_nth: Not an array"); - } - if (i >= value.array.size()) { - throw Error("extract_nth: index too large"); - } - return value.array[i]; -} - -Array& Datum::extract_array() { - if (type != Type::ARRAY) { - throw Error("get_array: Not an array"); - } - return value.array; -} - -Binary& Datum::extract_binary() { - if (type != Type::BINARY) { - throw Error("get_binary: Not a binary"); - } - return value.binary; -} - -Time& Datum::extract_time() { - if (type != Type::TIME) { - throw Error("get_time: Not a time"); - } - return value.time; -} - -int Datum::compare(const Datum& other) const { -#define COMPARE(a, b) do { \ - if (a < b) { return -1; } \ - if (a > b) { return 1; } } while(0) -#define COMPARE_OTHER(x) COMPARE(x, other.x) - - COMPARE_OTHER(type); - int c; - switch (type) { - case Type::NIL: case Type::INVALID: break; - case Type::BOOLEAN: COMPARE_OTHER(value.boolean); break; - case Type::NUMBER: COMPARE_OTHER(value.number); break; - case Type::STRING: - c = value.string.compare(other.value.string); - COMPARE(c, 0); - break; - case Type::BINARY: - c = value.binary.data.compare(other.value.binary.data); - COMPARE(c, 0); - break; - case Type::TIME: - COMPARE(value.time.epoch_time, other.value.time.epoch_time); - COMPARE(value.time.utc_offset, other.value.time.utc_offset); - break; - case Type::ARRAY: - COMPARE_OTHER(value.array.size()); - for (size_t i = 0; i < value.array.size(); i++) { - c = value.array[i].compare(other.value.array[i]); - COMPARE(c, 0); - } - break; - case Type::OBJECT: - COMPARE_OTHER(value.object.size()); - for (Object::const_iterator l = value.object.begin(), - r = other.value.object.begin(); - l != value.object.end(); - ++l, ++r) { - COMPARE(l->first, r->first); - c = l->second.compare(r->second); - COMPARE(c, 0); - } - break; - default: - throw Error("cannot compare invalid datum"); - } - return 0; -#undef COMPARE_OTHER -#undef COMPARE -} - -bool Datum::operator== (const Datum& other) const { - return compare(other) == 0; -} - -Datum Datum::from_raw() const { - do { - const Datum* type_field = get_field("$reql_type$"); - if (!type_field) break; - const std::string* type = type_field->get_string(); - if (!type) break;; - if (!strcmp(type->c_str(), "BINARY")) { - const Datum* data_field = get_field("data"); - if (!data_field) break; - const std::string* encoded_data = data_field->get_string(); - if (!encoded_data) break; - Binary binary(""); - if (base64_decode(*encoded_data, binary.data)) { - return binary; - } - } else if (!strcmp(type->c_str(), "TIME")) { - const Datum* epoch_field = get_field("epoch_time"); - if (!epoch_field) break; - const Datum* tz_field = get_field("timezone"); - if (!tz_field) break; - const double* epoch_time = epoch_field->get_number(); - if (!epoch_time) break; - const std::string* tz = tz_field->get_string(); - if (!tz) break; - double offset; - if (!Time::parse_utc_offset(*tz, &offset)) break; - return Time(*epoch_time, offset); - } - } while (0); - return *this; -} - -Datum Datum::to_raw() const { - if (type == Type::BINARY) { - return Object{ - {"$reql_type$", "BINARY"}, - {"data", base64_encode(value.binary.data)}}; - } else if (type == Type::TIME) { - return Object{ - {"$reql_type$", "TIME"}, - {"epoch_time", value.time.epoch_time}, - {"timezone", Time::utc_offset_string(value.time.utc_offset)}}; - } - return *this; -} - -Datum::Datum(Cursor&& cursor) : Datum(cursor.to_datum()) { } -Datum::Datum(const Cursor& cursor) : Datum(cursor.to_datum()) { } - -static const double max_dbl_int = 0x1LL << DBL_MANT_DIG; -static const double min_dbl_int = max_dbl_int * -1; -bool number_as_integer(double d, int64_t *i_out) { - static_assert(DBL_MANT_DIG == 53, "Doubles are wrong size."); - - if (min_dbl_int <= d && d <= max_dbl_int) { - int64_t i = d; - if (static_cast<double>(i) == d) { - *i_out = i; - return true; - } - } - return false; -} - -template void Datum::write_json( - rapidjson::Writer<rapidjson::StringBuffer> *writer) const; -template void Datum::write_json( - rapidjson::PrettyWriter<rapidjson::StringBuffer> *writer) const; - -template <class json_writer_t> -void Datum::write_json(json_writer_t *writer) const { - switch (type) { - case Type::NIL: writer->Null(); break; - case Type::BOOLEAN: writer->Bool(value.boolean); break; - case Type::NUMBER: { - const double d = value.number; - // Always print -0.0 as a double since integers cannot represent -0. - // Otherwise check if the number is an integer and print it as such. - int64_t i; - if (!(d == 0.0 && std::signbit(d)) && number_as_integer(d, &i)) { - writer->Int64(i); - } else { - writer->Double(d); - } - } break; - case Type::STRING: writer->String(value.string.data(), value.string.size()); break; - case Type::ARRAY: { - writer->StartArray(); - for (auto it : value.array) { - it.write_json(writer); - } - writer->EndArray(); - } break; - case Type::OBJECT: { - writer->StartObject(); - for (auto it : value.object) { - writer->Key(it.first.data(), it.first.size()); - it.second.write_json(writer); - } - writer->EndObject(); - } break; - - case Type::BINARY: - case Type::TIME: - to_raw().write_json(writer); - break; - default: - throw Error("cannot write invalid datum"); - } -} - -std::string Datum::as_json() const { - rapidjson::StringBuffer buffer; - rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); - write_json(&writer); - return std::string(buffer.GetString(), buffer.GetSize()); -} - -Datum Datum::from_json(const std::string& json) { - return read_datum(json); -} - -} // namespace RethinkDB |