X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fdynamic-inl.h;h=7b187d7c88509df00f6fafc1bcc459c58fa982fd;hp=1942452c5feb627366b4aa9fcfd531ea424f97c4;hb=f885995c00a27e0e440c0e5cb66ec3298fc507d4;hpb=b9836f4a8dc28c2641f027cf47c6604b7268e37f diff --git a/folly/dynamic-inl.h b/folly/dynamic-inl.h index 1942452c..7b187d7c 100644 --- a/folly/dynamic-inl.h +++ b/folly/dynamic-inl.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 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,134 +14,122 @@ * 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 ////////////////////////////////////////////////////////////////////// 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); + 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