X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fdynamic.cpp;h=8ef7d08ee6e4159efc7f484dc8262c86f5d0cf09;hb=0d38f5770ebf7e3ec987c55da719c29c2be3f3f2;hp=f7be57e8ca0dc5e9cb5fc00a014bee0aecb74313;hpb=8e48b79db72939d8ded148400c7f0572c6882ef9;p=folly.git diff --git a/folly/dynamic.cpp b/folly/dynamic.cpp index f7be57e8..8ef7d08e 100644 --- a/folly/dynamic.cpp +++ b/folly/dynamic.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +16,28 @@ #include +#include +#include +#include + namespace folly { ////////////////////////////////////////////////////////////////////// -#define DEF_TYPE(T, str, typen) \ - template<> char const dynamic::TypeInfo::name[] = str; \ - template<> dynamic::Type const dynamic::TypeInfo::type = typen +#define FOLLY_DYNAMIC_DEF_TYPEINFO(T) \ + constexpr const char* dynamic::TypeInfo::name; \ + constexpr dynamic::Type dynamic::TypeInfo::type; \ + // -DEF_TYPE(void*, "null", dynamic::NULLT); -DEF_TYPE(bool, "boolean", dynamic::BOOL); -DEF_TYPE(fbstring, "string", dynamic::STRING); -DEF_TYPE(dynamic::Array, "array", dynamic::ARRAY); -DEF_TYPE(double, "double", dynamic::DOUBLE); -DEF_TYPE(int64_t, "int64", dynamic::INT64); -DEF_TYPE(dynamic::ObjectImpl, "object", dynamic::OBJECT); +FOLLY_DYNAMIC_DEF_TYPEINFO(std::nullptr_t) +FOLLY_DYNAMIC_DEF_TYPEINFO(bool) +FOLLY_DYNAMIC_DEF_TYPEINFO(std::string) +FOLLY_DYNAMIC_DEF_TYPEINFO(dynamic::Array) +FOLLY_DYNAMIC_DEF_TYPEINFO(double) +FOLLY_DYNAMIC_DEF_TYPEINFO(int64_t) +FOLLY_DYNAMIC_DEF_TYPEINFO(dynamic::ObjectImpl) -#undef DEF_TYPE +#undef FOLLY_DYNAMIC_DEF_TYPEINFO const char* dynamic::typeName() const { return typeName(type_); @@ -56,18 +61,35 @@ TypeError::~TypeError() = default; // This is a higher-order preprocessor macro to aid going from runtime // types to the compile time type system. -#define FB_DYNAMIC_APPLY(type, apply) do { \ - switch ((type)) { \ - case NULLT: apply(void*); break; \ - case ARRAY: apply(Array); break; \ - case BOOL: apply(bool); break; \ - case DOUBLE: apply(double); break; \ - case INT64: apply(int64_t); break; \ - case OBJECT: apply(ObjectImpl); break; \ - case STRING: apply(fbstring); break; \ - default: CHECK(0); abort(); \ - } \ -} while (0) +#define FB_DYNAMIC_APPLY(type, apply) \ + do { \ + switch ((type)) { \ + case NULLT: \ + apply(std::nullptr_t); \ + break; \ + case ARRAY: \ + apply(Array); \ + break; \ + case BOOL: \ + apply(bool); \ + break; \ + case DOUBLE: \ + apply(double); \ + break; \ + case INT64: \ + apply(int64_t); \ + break; \ + case OBJECT: \ + apply(ObjectImpl); \ + break; \ + case STRING: \ + apply(std::string); \ + break; \ + default: \ + CHECK(0); \ + abort(); \ + } \ + } while (0) bool dynamic::operator<(dynamic const& o) const { if (UNLIKELY(type_ == OBJECT || o.type_ == OBJECT)) { @@ -132,7 +154,7 @@ dynamic& dynamic::operator=(dynamic&& o) noexcept { return *this; } -dynamic& dynamic::operator[](dynamic const& k) { +dynamic& dynamic::operator[](dynamic const& k) & { if (!isObject() && !isArray()) { throw TypeError("object/array", type()); } @@ -144,20 +166,38 @@ dynamic& dynamic::operator[](dynamic const& k) { return ret.first->second; } -dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) const { +dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) const& { auto& obj = get(); auto it = obj.find(k); return it == obj.end() ? v : it->second; } -dynamic&& dynamic::getDefault(const dynamic& k, dynamic&& v) const { +dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) const& { auto& obj = get(); auto it = obj.find(k); - if (it != obj.end()) { - v = it->second; + // Avoid clang bug with ternary + if (it == obj.end()) { + return std::move(v); + } else { + return it->second; } +} - return std::move(v); +dynamic dynamic::getDefault(const dynamic& k, const dynamic& v) && { + auto& obj = get(); + auto it = obj.find(k); + // Avoid clang bug with ternary + if (it == obj.end()) { + return v; + } else { + return std::move(it->second); + } +} + +dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) && { + auto& obj = get(); + auto it = obj.find(k); + return std::move(it == obj.end() ? v : it->second); } const dynamic* dynamic::get_ptr(dynamic const& idx) const& { @@ -168,7 +208,7 @@ const dynamic* dynamic::get_ptr(dynamic const& idx) const& { if (idx < 0 || idx >= parray->size()) { return nullptr; } - return &(*parray)[idx.asInt()]; + return &(*parray)[size_t(idx.asInt())]; } else if (auto* pobject = get_nothrow()) { auto it = pobject->find(idx); if (it == pobject->end()) { @@ -180,15 +220,15 @@ const dynamic* dynamic::get_ptr(dynamic const& idx) const& { } } -dynamic const& dynamic::at(dynamic const& idx) const { +dynamic const& dynamic::at(dynamic const& idx) const& { if (auto* parray = get_nothrow()) { if (!idx.isInt()) { throw TypeError("int64", idx.type()); } if (idx < 0 || idx >= parray->size()) { - throw std::out_of_range("out of range in dynamic array"); + std::__throw_out_of_range("out of range in dynamic array"); } - return (*parray)[idx.asInt()]; + return (*parray)[size_t(idx.asInt())]; } else if (auto* pobject = get_nothrow()) { auto it = pobject->find(idx); if (it == pobject->end()) { @@ -208,14 +248,13 @@ std::size_t dynamic::size() const { if (auto* obj = get_nothrow()) { return obj->size(); } - if (auto* str = get_nothrow()) { + if (auto* str = get_nothrow()) { return str->size(); } throw TypeError("array/object", type()); } -dynamic::const_iterator -dynamic::erase(const_iterator first, const_iterator last) { +dynamic::iterator dynamic::erase(const_iterator first, const_iterator last) { auto& arr = get(); return get().erase( arr.begin() + (first - arr.begin()), @@ -229,16 +268,18 @@ std::size_t dynamic::hash() const { case NULLT: throw TypeError("not null/object/array", type()); case INT64: - return std::hash()(asInt()); + return std::hash()(getInt()); case DOUBLE: - return std::hash()(asDouble()); + return std::hash()(getDouble()); case BOOL: - return std::hash()(asBool()); - case STRING: - return std::hash()(asString()); - default: - CHECK(0); abort(); + return std::hash()(getBool()); + case STRING: { + // keep it compatible with FBString + const auto& str = getString(); + return ::folly::hash::fnv32_buf(str.data(), str.size()); + } } + assume_unreachable(); } char const* dynamic::typeName(Type t) {