X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fdynamic-inl.h;h=324e7118ca3a7b8ca060450814ec10bfd3519f57;hb=16b7f86299f935fc16d38d72a8b497e2ab4a1d4f;hp=35378bd519fabd6421ff2c2ca300b6affe49cdaf;hpb=ce64f0f685111ac24c7a321ea56d0c3524621df1;p=folly.git diff --git a/folly/dynamic-inl.h b/folly/dynamic-inl.h index 35378bd5..324e7118 100644 --- a/folly/dynamic-inl.h +++ b/folly/dynamic-inl.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,18 +59,10 @@ struct hash< ::folly::dynamic> { namespace folly { struct TypeError : std::runtime_error { - explicit TypeError(const std::string& expected, dynamic::Type actual) - : std::runtime_error(to("TypeError: expected dynamic " - "type `", expected, '\'', ", but had type `", - dynamic::typeName(actual), '\'')) - {} + explicit TypeError(const std::string& expected, dynamic::Type actual); explicit 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), - '\'')) - {} + dynamic::Type actual1, dynamic::Type actual2); + ~TypeError(); }; @@ -309,13 +301,13 @@ inline dynamic::dynamic(dynamic const& o) *this = o; } -inline dynamic::dynamic(dynamic&& o) +inline dynamic::dynamic(dynamic&& o) noexcept : type_(NULLT) { *this = std::move(o); } -inline dynamic::~dynamic() { destroy(); } +inline dynamic::~dynamic() noexcept { destroy(); } template dynamic::dynamic(T t) { @@ -392,8 +384,19 @@ inline double dynamic::asDouble() const { return asImpl(); } inline int64_t dynamic::asInt() const { return asImpl(); } inline bool dynamic::asBool() const { return asImpl(); } +inline const fbstring& dynamic::getString() const { return get(); } +inline double dynamic::getDouble() const { return get(); } +inline int64_t dynamic::getInt() const { return get(); } +inline bool dynamic::getBool() const { return get(); } + +inline fbstring& dynamic::getString() { return get(); } +inline double& dynamic::getDouble() { return get(); } +inline int64_t& dynamic::getInt() { return get(); } +inline bool& dynamic::getBool() { return get(); } + inline const char* dynamic::data() const { return get().data(); } inline const char* dynamic::c_str() const { return get().c_str(); } +inline StringPiece dynamic::stringPiece() const { return get(); } template struct dynamic::CompareOp { @@ -407,35 +410,6 @@ struct dynamic::CompareOp { } }; -inline bool dynamic::operator<(dynamic const& o) const { - if (UNLIKELY(type_ == OBJECT || o.type_ == OBJECT)) { - throw TypeError("object", type_); - } - if (type_ != o.type_) { - return type_ < o.type_; - } - -#define FB_X(T) return CompareOp::comp(*getAddress(), \ - *o.getAddress()) - FB_DYNAMIC_APPLY(type_, FB_X); -#undef FB_X -} - -inline bool dynamic::operator==(dynamic const& o) const { - if (type() != o.type()) { - if (isNumber() && o.isNumber()) { - auto& integ = isInt() ? *this : o; - auto& doubl = isInt() ? o : *this; - return integ.asInt() == doubl.asDouble(); - } - return false; - } - -#define FB_X(T) return *getAddress() == *o.getAddress(); - FB_DYNAMIC_APPLY(type_, FB_X); -#undef FB_X -} - inline dynamic& dynamic::operator+=(dynamic const& o) { if (type() == STRING && o.type() == STRING) { *getAddress() += *o.getAddress(); @@ -486,60 +460,10 @@ inline dynamic& dynamic::operator--() { return *this; } -inline dynamic& dynamic::operator=(dynamic const& o) { - if (&o != this) { - destroy(); -#define FB_X(T) new (getAddress()) T(*o.getAddress()) - FB_DYNAMIC_APPLY(o.type_, FB_X); -#undef FB_X - type_ = o.type_; - } - return *this; -} - -inline dynamic& dynamic::operator=(dynamic&& o) { - if (&o != this) { - destroy(); -#define FB_X(T) new (getAddress()) T(std::move(*o.getAddress())) - FB_DYNAMIC_APPLY(o.type_, FB_X); -#undef FB_X - type_ = o.type_; - } - return *this; -} - -inline dynamic& dynamic::operator[](dynamic const& k) { - if (!isObject() && !isArray()) { - throw TypeError("object/array", type()); - } - if (isArray()) { - return at(k); - } - auto& obj = get(); - auto ret = obj.insert({k, nullptr}); - return ret.first->second; -} - inline dynamic const& dynamic::operator[](dynamic const& idx) const { return at(idx); } -inline 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; -} - -inline dynamic&& dynamic::getDefault(const dynamic& k, dynamic&& v) const { - auto& obj = get(); - auto it = obj.find(k); - if (it != obj.end()) { - v = it->second; - } - - return std::move(v); -} - template inline dynamic& dynamic::setDefault(K&& k, V&& v) { auto& obj = get(); return obj.insert(std::make_pair(std::forward(k), @@ -550,51 +474,10 @@ inline dynamic* dynamic::get_ptr(dynamic const& idx) { return const_cast(const_cast(this)->get_ptr(idx)); } -inline const dynamic* dynamic::get_ptr(dynamic const& idx) const { - if (auto* parray = get_nothrow()) { - if (!idx.isInt()) { - throw TypeError("int64", idx.type()); - } - if (idx >= parray->size()) { - return nullptr; - } - return &(*parray)[idx.asInt()]; - } else if (auto* pobject = get_nothrow()) { - auto it = pobject->find(idx); - if (it == pobject->end()) { - return nullptr; - } - return &it->second; - } else { - throw TypeError("object/array", type()); - } -} - inline dynamic& dynamic::at(dynamic const& idx) { return const_cast(const_cast(this)->at(idx)); } -inline dynamic const& dynamic::at(dynamic const& idx) const { - if (auto* parray = get_nothrow()) { - if (!idx.isInt()) { - throw TypeError("int64", idx.type()); - } - if (idx >= parray->size()) { - throw std::out_of_range("out of range in dynamic array"); - } - return (*parray)[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")); - } - return it->second; - } else { - throw TypeError("object/array", type()); - } -} - inline bool dynamic::empty() const { if (isNull()) { return true; @@ -602,19 +485,6 @@ inline bool dynamic::empty() const { return !size(); } -inline std::size_t dynamic::size() const { - if (auto* ar = get_nothrow()) { - return ar->size(); - } - if (auto* obj = get_nothrow()) { - return obj->size(); - } - if (auto* str = get_nothrow()) { - return str->size(); - } - throw TypeError("array/object", type()); -} - inline std::size_t dynamic::count(dynamic const& key) const { return find(key) != items().end(); } @@ -625,15 +495,8 @@ inline dynamic::const_item_iterator dynamic::find(dynamic const& key) const { template inline void dynamic::insert(K&& key, V&& val) { auto& obj = get(); - auto rv = obj.insert(std::make_pair(std::forward(key), - std::forward(val))); - if (!rv.second) { - // note, the second use of std:forward(val) is only correct - // if the first one did not result in a move. obj[key] = val - // would be preferrable but doesn't compile because dynamic - // is (intentionally) not default constructable - rv.first->second = std::forward(val); - } + auto rv = obj.insert({ std::forward(key), nullptr }); + rv.first->second = std::forward(val); } inline std::size_t dynamic::erase(dynamic const& key) { @@ -649,14 +512,6 @@ inline dynamic::const_iterator dynamic::erase(const_iterator it) { return get().erase(arr.begin() + (it - arr.begin())); } -inline dynamic::const_iterator -dynamic::erase(const_iterator first, const_iterator last) { - auto& arr = get(); - return get().erase( - arr.begin() + (first - arr.begin()), - arr.begin() + (last - arr.begin())); -} - inline dynamic::const_key_iterator dynamic::erase(const_key_iterator it) { return const_key_iterator(get().erase(it.base())); } @@ -707,25 +562,6 @@ inline void dynamic::pop_back() { array.pop_back(); } -inline std::size_t dynamic::hash() const { - switch (type()) { - case OBJECT: - case ARRAY: - case NULLT: - throw TypeError("not null/object/array", type()); - case INT64: - return std::hash()(asInt()); - case DOUBLE: - return std::hash()(asDouble()); - case BOOL: - return std::hash()(asBool()); - case STRING: - return std::hash()(asString()); - default: - CHECK(0); abort(); - } -} - ////////////////////////////////////////////////////////////////////// template struct dynamic::TypeInfo { @@ -761,7 +597,7 @@ T dynamic::asImpl() const { // Return a T* to our type, or null if we're not that type. template -T* dynamic::get_nothrow() { +T* dynamic::get_nothrow() noexcept { if (type_ != TypeInfo::type) { return nullptr; } @@ -769,40 +605,40 @@ T* dynamic::get_nothrow() { } template -T const* dynamic::get_nothrow() const { +T const* dynamic::get_nothrow() const noexcept { return const_cast(this)->get_nothrow(); } // Return T* for where we can put a T, without type checking. (Memory // might be uninitialized, even.) template -T* dynamic::getAddress() { +T* dynamic::getAddress() noexcept { return GetAddrImpl::get(u_); } template -T const* dynamic::getAddress() const { +T const* dynamic::getAddress() const noexcept { return const_cast(this)->getAddress(); } template struct dynamic::GetAddrImpl {}; template<> struct dynamic::GetAddrImpl { - static void** get(Data& d) { return &d.nul; } + static void** get(Data& d) noexcept { return &d.nul; } }; template<> struct dynamic::GetAddrImpl { - static Array* get(Data& d) { return &d.array; } + static Array* get(Data& d) noexcept { return &d.array; } }; template<> struct dynamic::GetAddrImpl { - static bool* get(Data& d) { return &d.boolean; } + static bool* get(Data& d) noexcept { return &d.boolean; } }; template<> struct dynamic::GetAddrImpl { - static int64_t* get(Data& d) { return &d.integer; } + static int64_t* get(Data& d) noexcept { return &d.integer; } }; template<> struct dynamic::GetAddrImpl { - static double* get(Data& d) { return &d.doubl; } + static double* get(Data& d) noexcept { return &d.doubl; } }; template<> struct dynamic::GetAddrImpl { - static fbstring* get(Data& d) { return &d.string; } + static fbstring* get(Data& d) noexcept { return &d.string; } }; template<> struct dynamic::GetAddrImpl { static_assert(sizeof(ObjectImpl) <= sizeof(Data::objectBuffer), @@ -810,7 +646,7 @@ template<> struct dynamic::GetAddrImpl { " amount of space depending on its template parameters. This is " "weird. Make objectBuffer bigger if you want to compile dynamic."); - static ObjectImpl* get(Data& d) { + static ObjectImpl* get(Data& d) noexcept { void* data = &d.objectBuffer; return static_cast(data); } @@ -829,23 +665,6 @@ T const& dynamic::get() const { return const_cast(this)->get(); } -inline char const* dynamic::typeName(Type t) { -#define FB_X(T) return TypeInfo::name - FB_DYNAMIC_APPLY(t, FB_X); -#undef FB_X -} - -inline void dynamic::destroy() { - // This short-circuit speeds up some microbenchmarks. - if (type_ == NULLT) return; - -#define FB_X(T) detail::Destroy::destroy(getAddress()) - FB_DYNAMIC_APPLY(type_, FB_X); -#undef FB_X - type_ = NULLT; - u_.nul = nullptr; -} - ////////////////////////////////////////////////////////////////////// /* @@ -946,7 +765,7 @@ class FormatValue> { case dynamic::ARRAY: { int key = arg.splitIntKey(); - if (key >= 0 && key < c.size()) { + if (key >= 0 && size_t(key) < c.size()) { FormatValue(c.at(key)).format(arg, cb); } else{ FormatValue(val_.defaultValue).format(arg, cb);