X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fdynamic.cpp;h=8c25017d3e4d85c7a740710fb185161e4b5963d5;hp=5e656c5e2d2acb0ce461942e9a88cbeefe295335;hb=171c36527455c2709be57f2ccc41218d45689411;hpb=eac2f407712046f9a3b91c244301467d31ec3819 diff --git a/folly/dynamic.cpp b/folly/dynamic.cpp index 5e656c5e..8c25017d 100644 --- a/folly/dynamic.cpp +++ b/folly/dynamic.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016 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. @@ -14,8 +14,11 @@ * limitations under the License. */ -#include #include + +#include +#include +#include #include namespace folly { @@ -27,7 +30,7 @@ namespace folly { constexpr dynamic::Type dynamic::TypeInfo::type; \ // -FOLLY_DYNAMIC_DEF_TYPEINFO(void*) +FOLLY_DYNAMIC_DEF_TYPEINFO(std::nullptr_t) FOLLY_DYNAMIC_DEF_TYPEINFO(bool) FOLLY_DYNAMIC_DEF_TYPEINFO(std::string) FOLLY_DYNAMIC_DEF_TYPEINFO(dynamic::Array) @@ -42,28 +45,43 @@ const char* dynamic::typeName() const { } TypeError::TypeError(const std::string& expected, dynamic::Type actual) - : std::runtime_error(to("TypeError: expected dynamic " - "type `", expected, '\'', ", but had type `", - dynamic::typeName(actual), '\'')) -{} - -TypeError::TypeError(const std::string& expected, - dynamic::Type actual1, dynamic::Type actual2) - : std::runtime_error(to("TypeError: expected dynamic " - "types `", expected, '\'', ", but had types `", - dynamic::typeName(actual1), "' and `", dynamic::typeName(actual2), - '\'')) -{} + : std::runtime_error(sformat( + "TypeError: expected dynamic type `{}', but had type `{}'", + expected, + dynamic::typeName(actual))) {} + +TypeError::TypeError( + const std::string& expected, + dynamic::Type actual1, + dynamic::Type actual2) + : std::runtime_error(sformat( + "TypeError: expected dynamic types `{}, but had types `{}' and `{}'", + expected, + dynamic::typeName(actual1), + dynamic::typeName(actual2))) {} TypeError::~TypeError() = default; +[[noreturn]] void throwTypeError_( + std::string const& expected, + dynamic::Type actual) { + throw TypeError(expected, actual); +} + +[[noreturn]] void throwTypeError_( + std::string const& expected, + dynamic::Type actual1, + dynamic::Type actual2) { + throw TypeError(expected, actual1, actual2); +} + // 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*); \ + apply(std::nullptr_t); \ break; \ case ARRAY: \ apply(Array); \ @@ -91,7 +109,7 @@ TypeError::~TypeError() = default; bool dynamic::operator<(dynamic const& o) const { if (UNLIKELY(type_ == OBJECT || o.type_ == OBJECT)) { - throw TypeError("object", type_); + throwTypeError_("object", type_); } if (type_ != o.type_) { return type_ < o.type_; @@ -154,7 +172,7 @@ dynamic& dynamic::operator=(dynamic&& o) noexcept { dynamic& dynamic::operator[](dynamic const& k) & { if (!isObject() && !isArray()) { - throw TypeError("object/array", type()); + throwTypeError_("object/array", type()); } if (isArray()) { return at(k); @@ -201,12 +219,12 @@ dynamic dynamic::getDefault(const dynamic& k, dynamic&& v) && { const dynamic* dynamic::get_ptr(dynamic const& idx) const& { if (auto* parray = get_nothrow()) { if (!idx.isInt()) { - throw TypeError("int64", idx.type()); + throwTypeError_("int64", idx.type()); } 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()) { @@ -214,28 +232,32 @@ const dynamic* dynamic::get_ptr(dynamic const& idx) const& { } return &it->second; } else { - throw TypeError("object/array", type()); + throwTypeError_("object/array", type()); } } +[[noreturn]] static void throwOutOfRangeAtMissingKey(dynamic const& idx) { + auto msg = sformat("couldn't find key {} in dynamic object", idx.asString()); + std::__throw_out_of_range(msg.c_str()); +} + dynamic const& dynamic::at(dynamic const& idx) const& { if (auto* parray = get_nothrow()) { if (!idx.isInt()) { - throw TypeError("int64", idx.type()); + throwTypeError_("int64", idx.type()); } if (idx < 0 || idx >= parray->size()) { 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()) { - throw std::out_of_range(to( - "couldn't find key ", idx.asString(), " in dynamic object")); + throwOutOfRangeAtMissingKey(idx); } return it->second; } else { - throw TypeError("object/array", type()); + throwTypeError_("object/array", type()); } } @@ -249,11 +271,10 @@ std::size_t dynamic::size() const { if (auto* str = get_nothrow()) { return str->size(); } - throw TypeError("array/object", type()); + throwTypeError_("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()), @@ -265,7 +286,7 @@ std::size_t dynamic::hash() const { case OBJECT: case ARRAY: case NULLT: - throw TypeError("not null/object/array", type()); + throwTypeError_("not null/object/array", type()); case INT64: return std::hash()(getInt()); case DOUBLE: @@ -277,9 +298,8 @@ std::size_t dynamic::hash() const { const auto& str = getString(); return ::folly::hash::fnv32_buf(str.data(), str.size()); } - default: - CHECK(0); abort(); } + assume_unreachable(); } char const* dynamic::typeName(Type t) { @@ -290,7 +310,9 @@ char const* dynamic::typeName(Type t) { void dynamic::destroy() noexcept { // This short-circuit speeds up some microbenchmarks. - if (type_ == NULLT) return; + if (type_ == NULLT) { + return; + } #define FB_X(T) detail::Destroy::destroy(getAddress()) FB_DYNAMIC_APPLY(type_, FB_X); @@ -301,4 +323,4 @@ void dynamic::destroy() noexcept { ////////////////////////////////////////////////////////////////////// -} +} // namespace folly