X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fdynamic-inl.h;h=61e6449cf296d356f11d2edc6e94a528544335d7;hp=204d48f91f7af271f92f58e995a4f6cc2efe8973;hb=e96129da65d3ad2b20aae5a2bf2d22d2d72b8feb;hpb=c2c66129648524ddb456fa44b35c1531dd103004 diff --git a/folly/dynamic-inl.h b/folly/dynamic-inl.h index 204d48f9..61e6449c 100644 --- a/folly/dynamic-inl.h +++ b/folly/dynamic-inl.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2011-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,135 +13,122 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifndef FOLLY_DYNAMIC_INL_H_ -#define FOLLY_DYNAMIC_INL_H_ +#pragma once #include + #include #include -#include "folly/Likely.h" -#include "folly/Conv.h" -#include "folly/Format.h" + +#include +#include +#include +#include ////////////////////////////////////////////////////////////////////// namespace std { -template<> -struct hash< ::folly::dynamic> { +template <> +struct hash<::folly::dynamic> { size_t operator()(::folly::dynamic const& d) const { return d.hash(); } }; -} +} // namespace std ////////////////////////////////////////////////////////////////////// // 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) ////////////////////////////////////////////////////////////////////// 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 actual1, dynamic::Type actual2) - : std::runtime_error(to("TypeError: expected dynamic " - "types `", expected, '\'', ", but had types `", - dynamic::typeName(actual1), "' and `", dynamic::typeName(actual2), - '\'')) - {} +struct FOLLY_EXPORT TypeError : std::runtime_error { + explicit TypeError(const std::string& expected, dynamic::Type actual); + explicit TypeError( + const std::string& expected, + dynamic::Type actual1, + dynamic::Type actual2); + ~TypeError() override; }; +[[noreturn]] void throwTypeError_( + std::string const& expected, + dynamic::Type actual); +[[noreturn]] void throwTypeError_( + std::string const& expected, + dynamic::Type actual1, + dynamic::Type actual2); ////////////////////////////////////////////////////////////////////// namespace detail { - // This helper is used in destroy() to be able to run destructors on - // types like "int64_t" without a compiler error. - struct Destroy { - template static void destroy(T* t) { t->~T(); } - }; - - /* - * The enable_if junk here is necessary to avoid ambiguous - * conversions relating to bool and double when you implicitly - * convert an int or long to a dynamic. - */ - template struct ConversionHelper; - template - struct ConversionHelper< - T, - typename std::enable_if< - std::is_integral::value && !std::is_same::value - >::type - > { - typedef int64_t type; - }; - template - struct ConversionHelper< - T, - typename std::enable_if< - (!std::is_integral::value || std::is_same::value) && - !std::is_same::value - >::type - > { - typedef T type; - }; - template - struct ConversionHelper< - T, - typename std::enable_if< - std::is_same::value - >::type - > { - typedef void* type; - }; - - /* - * Helper for implementing numeric conversions in operators on - * numbers. Just promotes to double when one of the arguments is - * double, or throws if either is not a numeric type. - */ - template class Op> - dynamic numericOp(dynamic const& a, dynamic const& b) { - if (!a.isNumber() || !b.isNumber()) { - throw TypeError("numeric", a.type(), b.type()); - } - if (a.type() != b.type()) { - auto& integ = a.isInt() ? a : b; - auto& nonint = a.isInt() ? b : a; - return Op()(to(integ.asInt()), nonint.asDouble()); - } - if (a.isDouble()) { - return Op()(a.asDouble(), b.asDouble()); - } - return Op()(a.asInt(), b.asInt()); +// This helper is used in destroy() to be able to run destructors on +// types like "int64_t" without a compiler error. +struct Destroy { + template + static void destroy(T* t) { + t->~T(); } +}; +/* + * Helper for implementing numeric conversions in operators on + * numbers. Just promotes to double when one of the arguments is + * double, or throws if either is not a numeric type. + */ +template