dynamic-inl.h 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. /*
  2. * Copyright 2011-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <functional>
  18. #include <folly/CPortability.h>
  19. #include <folly/Conv.h>
  20. #include <folly/Format.h>
  21. #include <folly/Likely.h>
  22. #include <folly/detail/Iterators.h>
  23. #include <folly/lang/Exception.h>
  24. namespace folly {
  25. namespace detail {
  26. struct DynamicHasher {
  27. using is_transparent = void;
  28. size_t operator()(dynamic const& d) const {
  29. return d.hash();
  30. }
  31. template <typename T>
  32. std::enable_if_t<std::is_convertible<T, StringPiece>::value, size_t>
  33. operator()(T const& val) const {
  34. // keep consistent with dynamic::hash() for strings
  35. return Hash()(static_cast<StringPiece>(val));
  36. }
  37. };
  38. struct DynamicKeyEqual {
  39. using is_transparent = void;
  40. bool operator()(const dynamic& lhs, const dynamic& rhs) const {
  41. return std::equal_to<dynamic>()(lhs, rhs);
  42. }
  43. // Dynamic objects contains a map<dynamic, dynamic>. At least one of the
  44. // operands should be a dynamic. Hence, an operator() where both operands are
  45. // convertible to StringPiece is unnecessary.
  46. template <typename A, typename B>
  47. std::enable_if_t<
  48. std::is_convertible<A, StringPiece>::value &&
  49. std::is_convertible<B, StringPiece>::value,
  50. bool>
  51. operator()(A const& lhs, B const& rhs) const = delete;
  52. template <typename A>
  53. std::enable_if_t<std::is_convertible<A, StringPiece>::value, bool> operator()(
  54. A const& lhs,
  55. dynamic const& rhs) const {
  56. return FOLLY_LIKELY(rhs.type() == dynamic::Type::STRING) &&
  57. std::equal_to<StringPiece>()(lhs, rhs.stringPiece());
  58. }
  59. template <typename B>
  60. std::enable_if_t<std::is_convertible<B, StringPiece>::value, bool> operator()(
  61. dynamic const& lhs,
  62. B const& rhs) const {
  63. return FOLLY_LIKELY(lhs.type() == dynamic::Type::STRING) &&
  64. std::equal_to<StringPiece>()(lhs.stringPiece(), rhs);
  65. }
  66. };
  67. } // namespace detail
  68. } // namespace folly
  69. //////////////////////////////////////////////////////////////////////
  70. namespace std {
  71. template <>
  72. struct hash<::folly::dynamic> {
  73. size_t operator()(::folly::dynamic const& d) const {
  74. return d.hash();
  75. }
  76. };
  77. } // namespace std
  78. //////////////////////////////////////////////////////////////////////
  79. // This is a higher-order preprocessor macro to aid going from runtime
  80. // types to the compile time type system.
  81. #define FB_DYNAMIC_APPLY(type, apply) \
  82. do { \
  83. switch ((type)) { \
  84. case NULLT: \
  85. apply(std::nullptr_t); \
  86. break; \
  87. case ARRAY: \
  88. apply(Array); \
  89. break; \
  90. case BOOL: \
  91. apply(bool); \
  92. break; \
  93. case DOUBLE: \
  94. apply(double); \
  95. break; \
  96. case INT64: \
  97. apply(int64_t); \
  98. break; \
  99. case OBJECT: \
  100. apply(ObjectImpl); \
  101. break; \
  102. case STRING: \
  103. apply(std::string); \
  104. break; \
  105. default: \
  106. CHECK(0); \
  107. abort(); \
  108. } \
  109. } while (0)
  110. //////////////////////////////////////////////////////////////////////
  111. namespace folly {
  112. struct FOLLY_EXPORT TypeError : std::runtime_error {
  113. explicit TypeError(const std::string& expected, dynamic::Type actual);
  114. explicit TypeError(
  115. const std::string& expected,
  116. dynamic::Type actual1,
  117. dynamic::Type actual2);
  118. // TODO: noexcept calculation required through gcc-v4.9; remove once upgrading
  119. // to gcc-v5.
  120. TypeError(const TypeError&) noexcept(
  121. std::is_nothrow_copy_constructible<std::runtime_error>::value);
  122. TypeError& operator=(const TypeError&) noexcept(
  123. std::is_nothrow_copy_assignable<std::runtime_error>::value);
  124. TypeError(TypeError&&) noexcept(
  125. std::is_nothrow_move_constructible<std::runtime_error>::value);
  126. TypeError& operator=(TypeError&&) noexcept(
  127. std::is_nothrow_move_assignable<std::runtime_error>::value);
  128. ~TypeError() override;
  129. };
  130. //////////////////////////////////////////////////////////////////////
  131. namespace detail {
  132. // This helper is used in destroy() to be able to run destructors on
  133. // types like "int64_t" without a compiler error.
  134. struct Destroy {
  135. template <class T>
  136. static void destroy(T* t) {
  137. t->~T();
  138. }
  139. };
  140. /*
  141. * Helper for implementing numeric conversions in operators on
  142. * numbers. Just promotes to double when one of the arguments is
  143. * double, or throws if either is not a numeric type.
  144. */
  145. template <template <class> class Op>
  146. dynamic numericOp(dynamic const& a, dynamic const& b) {
  147. if (!a.isNumber() || !b.isNumber()) {
  148. throw_exception<TypeError>("numeric", a.type(), b.type());
  149. }
  150. if (a.type() != b.type()) {
  151. auto& integ = a.isInt() ? a : b;
  152. auto& nonint = a.isInt() ? b : a;
  153. return Op<double>()(to<double>(integ.asInt()), nonint.asDouble());
  154. }
  155. if (a.isDouble()) {
  156. return Op<double>()(a.asDouble(), b.asDouble());
  157. }
  158. return Op<int64_t>()(a.asInt(), b.asInt());
  159. }
  160. } // namespace detail
  161. //////////////////////////////////////////////////////////////////////
  162. /*
  163. * We're doing this instead of a simple member typedef to avoid the
  164. * undefined behavior of parameterizing F14NodeMap<> with an
  165. * incomplete type.
  166. *
  167. * Note: Later we may add separate order tracking here (a multi-index
  168. * type of thing.)
  169. */
  170. struct dynamic::ObjectImpl : F14NodeMap<
  171. dynamic,
  172. dynamic,
  173. detail::DynamicHasher,
  174. detail::DynamicKeyEqual> {};
  175. //////////////////////////////////////////////////////////////////////
  176. // Helper object for creating objects conveniently. See object and
  177. // the dynamic::dynamic(ObjectMaker&&) ctor.
  178. struct dynamic::ObjectMaker {
  179. friend struct dynamic;
  180. explicit ObjectMaker() : val_(dynamic::object) {}
  181. explicit ObjectMaker(dynamic key, dynamic val) : val_(dynamic::object) {
  182. val_.insert(std::move(key), std::move(val));
  183. }
  184. // Make sure no one tries to save one of these into an lvalue with
  185. // auto or anything like that.
  186. ObjectMaker(ObjectMaker&&) = default;
  187. ObjectMaker(ObjectMaker const&) = delete;
  188. ObjectMaker& operator=(ObjectMaker const&) = delete;
  189. ObjectMaker& operator=(ObjectMaker&&) = delete;
  190. // This returns an rvalue-reference instead of an lvalue-reference
  191. // to allow constructs like this to moved instead of copied:
  192. // dynamic a = dynamic::object("a", "b")("c", "d")
  193. ObjectMaker&& operator()(dynamic key, dynamic val) {
  194. val_.insert(std::move(key), std::move(val));
  195. return std::move(*this);
  196. }
  197. private:
  198. dynamic val_;
  199. };
  200. inline void dynamic::array(EmptyArrayTag) {}
  201. template <class... Args>
  202. inline dynamic dynamic::array(Args&&... args) {
  203. return dynamic(Array{std::forward<Args>(args)...});
  204. }
  205. inline dynamic::ObjectMaker dynamic::object() {
  206. return ObjectMaker();
  207. }
  208. inline dynamic::ObjectMaker dynamic::object(dynamic a, dynamic b) {
  209. return ObjectMaker(std::move(a), std::move(b));
  210. }
  211. //////////////////////////////////////////////////////////////////////
  212. struct dynamic::item_iterator : detail::IteratorAdaptor<
  213. dynamic::item_iterator,
  214. dynamic::ObjectImpl::iterator,
  215. std::pair<dynamic const, dynamic>> {
  216. using Super = detail::IteratorAdaptor<
  217. dynamic::item_iterator,
  218. dynamic::ObjectImpl::iterator,
  219. std::pair<dynamic const, dynamic>>;
  220. /* implicit */ item_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {}
  221. using object_type = dynamic::ObjectImpl;
  222. };
  223. struct dynamic::value_iterator : detail::IteratorAdaptor<
  224. dynamic::value_iterator,
  225. dynamic::ObjectImpl::iterator,
  226. dynamic> {
  227. using Super = detail::IteratorAdaptor<
  228. dynamic::value_iterator,
  229. dynamic::ObjectImpl::iterator,
  230. dynamic>;
  231. /* implicit */ value_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {}
  232. using object_type = dynamic::ObjectImpl;
  233. dynamic& dereference() const {
  234. return base()->second;
  235. }
  236. };
  237. struct dynamic::const_item_iterator
  238. : detail::IteratorAdaptor<
  239. dynamic::const_item_iterator,
  240. dynamic::ObjectImpl::const_iterator,
  241. std::pair<dynamic const, dynamic> const> {
  242. using Super = detail::IteratorAdaptor<
  243. dynamic::const_item_iterator,
  244. dynamic::ObjectImpl::const_iterator,
  245. std::pair<dynamic const, dynamic> const>;
  246. /* implicit */ const_item_iterator(dynamic::ObjectImpl::const_iterator b)
  247. : Super(b) {}
  248. /* implicit */ const_item_iterator(const_item_iterator const& i)
  249. : Super(i.base()) {}
  250. /* implicit */ const_item_iterator(item_iterator i) : Super(i.base()) {}
  251. using object_type = dynamic::ObjectImpl const;
  252. };
  253. struct dynamic::const_key_iterator : detail::IteratorAdaptor<
  254. dynamic::const_key_iterator,
  255. dynamic::ObjectImpl::const_iterator,
  256. dynamic const> {
  257. using Super = detail::IteratorAdaptor<
  258. dynamic::const_key_iterator,
  259. dynamic::ObjectImpl::const_iterator,
  260. dynamic const>;
  261. /* implicit */ const_key_iterator(dynamic::ObjectImpl::const_iterator b)
  262. : Super(b) {}
  263. using object_type = dynamic::ObjectImpl const;
  264. dynamic const& dereference() const {
  265. return base()->first;
  266. }
  267. };
  268. struct dynamic::const_value_iterator : detail::IteratorAdaptor<
  269. dynamic::const_value_iterator,
  270. dynamic::ObjectImpl::const_iterator,
  271. dynamic const> {
  272. using Super = detail::IteratorAdaptor<
  273. dynamic::const_value_iterator,
  274. dynamic::ObjectImpl::const_iterator,
  275. dynamic const>;
  276. /* implicit */ const_value_iterator(dynamic::ObjectImpl::const_iterator b)
  277. : Super(b) {}
  278. /* implicit */ const_value_iterator(value_iterator i) : Super(i.base()) {}
  279. /* implicit */ const_value_iterator(dynamic::ObjectImpl::iterator i)
  280. : Super(i) {}
  281. using object_type = dynamic::ObjectImpl const;
  282. dynamic const& dereference() const {
  283. return base()->second;
  284. }
  285. };
  286. //////////////////////////////////////////////////////////////////////
  287. inline dynamic::dynamic() : dynamic(nullptr) {}
  288. inline dynamic::dynamic(std::nullptr_t) : type_(NULLT) {}
  289. inline dynamic::dynamic(void (*)(EmptyArrayTag)) : type_(ARRAY) {
  290. new (&u_.array) Array();
  291. }
  292. inline dynamic::dynamic(ObjectMaker (*)()) : type_(OBJECT) {
  293. new (getAddress<ObjectImpl>()) ObjectImpl();
  294. }
  295. inline dynamic::dynamic(StringPiece s) : type_(STRING) {
  296. new (&u_.string) std::string(s.data(), s.size());
  297. }
  298. inline dynamic::dynamic(char const* s) : type_(STRING) {
  299. new (&u_.string) std::string(s);
  300. }
  301. inline dynamic::dynamic(std::string s) : type_(STRING) {
  302. new (&u_.string) std::string(std::move(s));
  303. }
  304. inline dynamic::dynamic(ObjectMaker&& maker) : type_(OBJECT) {
  305. new (getAddress<ObjectImpl>())
  306. ObjectImpl(std::move(*maker.val_.getAddress<ObjectImpl>()));
  307. }
  308. inline dynamic::dynamic(dynamic const& o) : type_(NULLT) {
  309. *this = o;
  310. }
  311. inline dynamic::dynamic(dynamic&& o) noexcept : type_(NULLT) {
  312. *this = std::move(o);
  313. }
  314. inline dynamic::~dynamic() noexcept {
  315. destroy();
  316. }
  317. // Integral types except bool convert to int64_t, float types to double.
  318. template <class T>
  319. struct dynamic::NumericTypeHelper<
  320. T,
  321. typename std::enable_if<std::is_integral<T>::value>::type> {
  322. static_assert(
  323. !kIsObjC || sizeof(T) > sizeof(char),
  324. "char-sized types are ambiguous in objc; cast to bool or wider type");
  325. using type = int64_t;
  326. };
  327. template <>
  328. struct dynamic::NumericTypeHelper<bool> {
  329. using type = bool;
  330. };
  331. template <>
  332. struct dynamic::NumericTypeHelper<float> {
  333. using type = double;
  334. };
  335. template <>
  336. struct dynamic::NumericTypeHelper<double> {
  337. using type = double;
  338. };
  339. inline dynamic::dynamic(std::vector<bool>::reference b)
  340. : dynamic(static_cast<bool>(b)) {}
  341. inline dynamic::dynamic(VectorBoolConstRefCtorType b)
  342. : dynamic(static_cast<bool>(b)) {}
  343. template <
  344. class T,
  345. class NumericType /* = typename NumericTypeHelper<T>::type */>
  346. dynamic::dynamic(T t) {
  347. type_ = TypeInfo<NumericType>::type;
  348. new (getAddress<NumericType>()) NumericType(NumericType(t));
  349. }
  350. template <class Iterator>
  351. dynamic::dynamic(Iterator first, Iterator last) : type_(ARRAY) {
  352. new (&u_.array) Array(first, last);
  353. }
  354. //////////////////////////////////////////////////////////////////////
  355. inline dynamic::const_iterator dynamic::begin() const {
  356. return get<Array>().begin();
  357. }
  358. inline dynamic::const_iterator dynamic::end() const {
  359. return get<Array>().end();
  360. }
  361. inline dynamic::iterator dynamic::begin() {
  362. return get<Array>().begin();
  363. }
  364. inline dynamic::iterator dynamic::end() {
  365. return get<Array>().end();
  366. }
  367. template <class It>
  368. struct dynamic::IterableProxy {
  369. typedef It iterator;
  370. typedef typename It::value_type value_type;
  371. typedef typename It::object_type object_type;
  372. /* implicit */ IterableProxy(object_type* o) : o_(o) {}
  373. It begin() const {
  374. return o_->begin();
  375. }
  376. It end() const {
  377. return o_->end();
  378. }
  379. private:
  380. object_type* o_;
  381. };
  382. inline dynamic::IterableProxy<dynamic::const_key_iterator> dynamic::keys()
  383. const {
  384. return &(get<ObjectImpl>());
  385. }
  386. inline dynamic::IterableProxy<dynamic::const_value_iterator> dynamic::values()
  387. const {
  388. return &(get<ObjectImpl>());
  389. }
  390. inline dynamic::IterableProxy<dynamic::const_item_iterator> dynamic::items()
  391. const {
  392. return &(get<ObjectImpl>());
  393. }
  394. inline dynamic::IterableProxy<dynamic::value_iterator> dynamic::values() {
  395. return &(get<ObjectImpl>());
  396. }
  397. inline dynamic::IterableProxy<dynamic::item_iterator> dynamic::items() {
  398. return &(get<ObjectImpl>());
  399. }
  400. inline bool dynamic::isString() const {
  401. return get_nothrow<std::string>() != nullptr;
  402. }
  403. inline bool dynamic::isObject() const {
  404. return get_nothrow<ObjectImpl>() != nullptr;
  405. }
  406. inline bool dynamic::isBool() const {
  407. return get_nothrow<bool>() != nullptr;
  408. }
  409. inline bool dynamic::isArray() const {
  410. return get_nothrow<Array>() != nullptr;
  411. }
  412. inline bool dynamic::isDouble() const {
  413. return get_nothrow<double>() != nullptr;
  414. }
  415. inline bool dynamic::isInt() const {
  416. return get_nothrow<int64_t>() != nullptr;
  417. }
  418. inline bool dynamic::isNull() const {
  419. return get_nothrow<std::nullptr_t>() != nullptr;
  420. }
  421. inline bool dynamic::isNumber() const {
  422. return isInt() || isDouble();
  423. }
  424. inline dynamic::Type dynamic::type() const {
  425. return type_;
  426. }
  427. inline std::string dynamic::asString() const {
  428. return asImpl<std::string>();
  429. }
  430. inline double dynamic::asDouble() const {
  431. return asImpl<double>();
  432. }
  433. inline int64_t dynamic::asInt() const {
  434. return asImpl<int64_t>();
  435. }
  436. inline bool dynamic::asBool() const {
  437. return asImpl<bool>();
  438. }
  439. inline const std::string& dynamic::getString() const& {
  440. return get<std::string>();
  441. }
  442. inline double dynamic::getDouble() const& {
  443. return get<double>();
  444. }
  445. inline int64_t dynamic::getInt() const& {
  446. return get<int64_t>();
  447. }
  448. inline bool dynamic::getBool() const& {
  449. return get<bool>();
  450. }
  451. inline std::string& dynamic::getString() & {
  452. return get<std::string>();
  453. }
  454. inline double& dynamic::getDouble() & {
  455. return get<double>();
  456. }
  457. inline int64_t& dynamic::getInt() & {
  458. return get<int64_t>();
  459. }
  460. inline bool& dynamic::getBool() & {
  461. return get<bool>();
  462. }
  463. inline std::string&& dynamic::getString() && {
  464. return std::move(get<std::string>());
  465. }
  466. inline double dynamic::getDouble() && {
  467. return get<double>();
  468. }
  469. inline int64_t dynamic::getInt() && {
  470. return get<int64_t>();
  471. }
  472. inline bool dynamic::getBool() && {
  473. return get<bool>();
  474. }
  475. inline const char* dynamic::data() const& {
  476. return get<std::string>().data();
  477. }
  478. inline const char* dynamic::c_str() const& {
  479. return get<std::string>().c_str();
  480. }
  481. inline StringPiece dynamic::stringPiece() const {
  482. return get<std::string>();
  483. }
  484. template <class T>
  485. struct dynamic::CompareOp {
  486. static bool comp(T const& a, T const& b) {
  487. return a < b;
  488. }
  489. };
  490. template <>
  491. struct dynamic::CompareOp<dynamic::ObjectImpl> {
  492. static bool comp(ObjectImpl const&, ObjectImpl const&) {
  493. // This code never executes; it is just here for the compiler.
  494. return false;
  495. }
  496. };
  497. template <>
  498. struct dynamic::CompareOp<std::nullptr_t> {
  499. static bool comp(std::nullptr_t const&, std::nullptr_t const&) {
  500. return true;
  501. }
  502. };
  503. inline dynamic& dynamic::operator+=(dynamic const& o) {
  504. if (type() == STRING && o.type() == STRING) {
  505. *getAddress<std::string>() += *o.getAddress<std::string>();
  506. return *this;
  507. }
  508. *this = detail::numericOp<std::plus>(*this, o);
  509. return *this;
  510. }
  511. inline dynamic& dynamic::operator-=(dynamic const& o) {
  512. *this = detail::numericOp<std::minus>(*this, o);
  513. return *this;
  514. }
  515. inline dynamic& dynamic::operator*=(dynamic const& o) {
  516. *this = detail::numericOp<std::multiplies>(*this, o);
  517. return *this;
  518. }
  519. inline dynamic& dynamic::operator/=(dynamic const& o) {
  520. *this = detail::numericOp<std::divides>(*this, o);
  521. return *this;
  522. }
  523. #define FB_DYNAMIC_INTEGER_OP(op) \
  524. inline dynamic& dynamic::operator op(dynamic const& o) { \
  525. if (!isInt() || !o.isInt()) { \
  526. throw_exception<TypeError>("int64", type(), o.type()); \
  527. } \
  528. *getAddress<int64_t>() op o.asInt(); \
  529. return *this; \
  530. }
  531. FB_DYNAMIC_INTEGER_OP(%=)
  532. FB_DYNAMIC_INTEGER_OP(|=)
  533. FB_DYNAMIC_INTEGER_OP(&=)
  534. FB_DYNAMIC_INTEGER_OP(^=)
  535. #undef FB_DYNAMIC_INTEGER_OP
  536. inline dynamic& dynamic::operator++() {
  537. ++get<int64_t>();
  538. return *this;
  539. }
  540. inline dynamic& dynamic::operator--() {
  541. --get<int64_t>();
  542. return *this;
  543. }
  544. template <typename K>
  545. dynamic::IfIsNonStringDynamicConvertible<K, dynamic const&> dynamic::operator[](
  546. K&& idx) const& {
  547. return at(std::forward<K>(idx));
  548. }
  549. template <typename K>
  550. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::operator[](
  551. K&& idx) & {
  552. if (!isObject() && !isArray()) {
  553. throw_exception<TypeError>("object/array", type());
  554. }
  555. if (isArray()) {
  556. return at(std::forward<K>(idx));
  557. }
  558. auto& obj = get<ObjectImpl>();
  559. auto ret = obj.emplace(std::forward<K>(idx), nullptr);
  560. return ret.first->second;
  561. }
  562. template <typename K>
  563. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&&> dynamic::operator[](
  564. K&& idx) && {
  565. return std::move((*this)[std::forward<K>(idx)]);
  566. }
  567. inline dynamic const& dynamic::operator[](StringPiece k) const& {
  568. return at(k);
  569. }
  570. inline dynamic&& dynamic::operator[](StringPiece k) && {
  571. return std::move((*this)[k]);
  572. }
  573. template <typename K>
  574. dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
  575. K&& k,
  576. const dynamic& v) const& {
  577. auto& obj = get<ObjectImpl>();
  578. auto it = obj.find(std::forward<K>(k));
  579. return it == obj.end() ? v : it->second;
  580. }
  581. template <typename K>
  582. dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
  583. K&& k,
  584. dynamic&& v) const& {
  585. auto& obj = get<ObjectImpl>();
  586. auto it = obj.find(std::forward<K>(k));
  587. // Avoid clang bug with ternary
  588. if (it == obj.end()) {
  589. return std::move(v);
  590. } else {
  591. return it->second;
  592. }
  593. }
  594. template <typename K>
  595. dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
  596. K&& k,
  597. const dynamic& v) && {
  598. auto& obj = get<ObjectImpl>();
  599. auto it = obj.find(std::forward<K>(k));
  600. // Avoid clang bug with ternary
  601. if (it == obj.end()) {
  602. return v;
  603. } else {
  604. return std::move(it->second);
  605. }
  606. }
  607. template <typename K>
  608. dynamic::IfIsNonStringDynamicConvertible<K, dynamic> dynamic::getDefault(
  609. K&& k,
  610. dynamic&& v) && {
  611. auto& obj = get<ObjectImpl>();
  612. auto it = obj.find(std::forward<K>(k));
  613. return std::move(it == obj.end() ? v : it->second);
  614. }
  615. template <typename K, typename V>
  616. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault(
  617. K&& k,
  618. V&& v) {
  619. auto& obj = get<ObjectImpl>();
  620. return obj.emplace(std::forward<K>(k), std::forward<V>(v)).first->second;
  621. }
  622. template <typename K>
  623. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault(
  624. K&& k,
  625. dynamic&& v) {
  626. auto& obj = get<ObjectImpl>();
  627. return obj.emplace(std::forward<K>(k), std::move(v)).first->second;
  628. }
  629. template <typename K>
  630. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::setDefault(
  631. K&& k,
  632. const dynamic& v) {
  633. auto& obj = get<ObjectImpl>();
  634. return obj.emplace(std::forward<K>(k), v).first->second;
  635. }
  636. template <typename V>
  637. dynamic& dynamic::setDefault(StringPiece k, V&& v) {
  638. auto& obj = get<ObjectImpl>();
  639. return obj.emplace(k, std::forward<V>(v)).first->second;
  640. }
  641. inline dynamic& dynamic::setDefault(StringPiece k, dynamic&& v) {
  642. auto& obj = get<ObjectImpl>();
  643. return obj.emplace(k, std::move(v)).first->second;
  644. }
  645. inline dynamic& dynamic::setDefault(StringPiece k, const dynamic& v) {
  646. auto& obj = get<ObjectImpl>();
  647. return obj.emplace(k, v).first->second;
  648. }
  649. template <typename K>
  650. dynamic::IfIsNonStringDynamicConvertible<K, dynamic const*> dynamic::get_ptr(
  651. K&& k) const& {
  652. return get_ptrImpl(std::forward<K>(k));
  653. }
  654. template <typename K>
  655. dynamic::IfIsNonStringDynamicConvertible<K, dynamic*> dynamic::get_ptr(
  656. K&& idx) & {
  657. return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx));
  658. }
  659. inline dynamic* dynamic::get_ptr(StringPiece idx) & {
  660. return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx));
  661. }
  662. inline dynamic* dynamic::get_ptr(json_pointer const& jsonPtr) & {
  663. return const_cast<dynamic*>(
  664. const_cast<dynamic const*>(this)->get_ptr(jsonPtr));
  665. }
  666. template <typename K>
  667. dynamic::IfIsNonStringDynamicConvertible<K, dynamic const&> dynamic::at(
  668. K&& k) const& {
  669. return atImpl(std::forward<K>(k));
  670. }
  671. template <typename K>
  672. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&> dynamic::at(K&& idx) & {
  673. return const_cast<dynamic&>(const_cast<dynamic const*>(this)->at(idx));
  674. }
  675. template <typename K>
  676. dynamic::IfIsNonStringDynamicConvertible<K, dynamic&&> dynamic::at(K&& idx) && {
  677. return std::move(at(idx));
  678. }
  679. inline dynamic& dynamic::at(StringPiece idx) & {
  680. return const_cast<dynamic&>(const_cast<dynamic const*>(this)->at(idx));
  681. }
  682. inline dynamic&& dynamic::at(StringPiece idx) && {
  683. return std::move(at(idx));
  684. }
  685. inline bool dynamic::empty() const {
  686. if (isNull()) {
  687. return true;
  688. }
  689. return !size();
  690. }
  691. template <typename K>
  692. dynamic::IfIsNonStringDynamicConvertible<K, dynamic::const_item_iterator>
  693. dynamic::find(K&& key) const {
  694. return get<ObjectImpl>().find(std::forward<K>(key));
  695. }
  696. template <typename K>
  697. dynamic::IfIsNonStringDynamicConvertible<K, dynamic::item_iterator>
  698. dynamic::find(K&& key) {
  699. return get<ObjectImpl>().find(std::forward<K>(key));
  700. }
  701. inline dynamic::const_item_iterator dynamic::find(StringPiece key) const {
  702. return get<ObjectImpl>().find(key);
  703. }
  704. inline dynamic::item_iterator dynamic::find(StringPiece key) {
  705. return get<ObjectImpl>().find(key);
  706. }
  707. template <typename K>
  708. dynamic::IfIsNonStringDynamicConvertible<K, std::size_t> dynamic::count(
  709. K&& key) const {
  710. return find(std::forward<K>(key)) != items().end() ? 1u : 0u;
  711. }
  712. inline std::size_t dynamic::count(StringPiece key) const {
  713. return find(key) != items().end() ? 1u : 0u;
  714. }
  715. template <class K, class V>
  716. inline void dynamic::insert(K&& key, V&& val) {
  717. auto& obj = get<ObjectImpl>();
  718. obj[std::forward<K>(key)] = std::forward<V>(val);
  719. }
  720. inline void dynamic::update(const dynamic& mergeObj) {
  721. if (!isObject() || !mergeObj.isObject()) {
  722. throw_exception<TypeError>("object", type(), mergeObj.type());
  723. }
  724. for (const auto& pair : mergeObj.items()) {
  725. (*this)[pair.first] = pair.second;
  726. }
  727. }
  728. inline void dynamic::update_missing(const dynamic& mergeObj1) {
  729. if (!isObject() || !mergeObj1.isObject()) {
  730. throw_exception<TypeError>("object", type(), mergeObj1.type());
  731. }
  732. // Only add if not already there
  733. for (const auto& pair : mergeObj1.items()) {
  734. if ((*this).find(pair.first) == (*this).items().end()) {
  735. (*this)[pair.first] = pair.second;
  736. }
  737. }
  738. }
  739. inline void dynamic::merge_patch(const dynamic& patch) {
  740. auto& self = *this;
  741. if (!patch.isObject()) {
  742. self = patch;
  743. return;
  744. }
  745. // if we are not an object, erase all contents, reset to object
  746. if (!isObject()) {
  747. self = object;
  748. }
  749. for (const auto& pair : patch.items()) {
  750. if (pair.second.isNull()) {
  751. // if name could be found in current object, remove it
  752. auto it = self.find(pair.first);
  753. if (it != self.items().end()) {
  754. self.erase(it);
  755. }
  756. } else {
  757. self[pair.first].merge_patch(pair.second);
  758. }
  759. }
  760. }
  761. inline dynamic dynamic::merge(
  762. const dynamic& mergeObj1,
  763. const dynamic& mergeObj2) {
  764. // No checks on type needed here because they are done in update_missing
  765. // Note that we do update_missing here instead of update() because
  766. // it will prevent the extra writes that would occur with update()
  767. auto ret = mergeObj2;
  768. ret.update_missing(mergeObj1);
  769. return ret;
  770. }
  771. template <typename K>
  772. dynamic::IfIsNonStringDynamicConvertible<K, std::size_t> dynamic::erase(
  773. K&& key) {
  774. auto& obj = get<ObjectImpl>();
  775. return obj.erase(std::forward<K>(key));
  776. }
  777. inline std::size_t dynamic::erase(StringPiece key) {
  778. auto& obj = get<ObjectImpl>();
  779. return obj.erase(key);
  780. }
  781. inline dynamic::iterator dynamic::erase(const_iterator it) {
  782. auto& arr = get<Array>();
  783. // std::vector doesn't have an erase method that works on const iterators,
  784. // even though the standard says it should, so this hack converts to a
  785. // non-const iterator before calling erase.
  786. return get<Array>().erase(arr.begin() + (it - arr.begin()));
  787. }
  788. inline dynamic::const_key_iterator dynamic::erase(const_key_iterator it) {
  789. return const_key_iterator(get<ObjectImpl>().erase(it.base()));
  790. }
  791. inline dynamic::const_key_iterator dynamic::erase(
  792. const_key_iterator first,
  793. const_key_iterator last) {
  794. return const_key_iterator(get<ObjectImpl>().erase(first.base(), last.base()));
  795. }
  796. inline dynamic::value_iterator dynamic::erase(const_value_iterator it) {
  797. return value_iterator(get<ObjectImpl>().erase(it.base()));
  798. }
  799. inline dynamic::value_iterator dynamic::erase(
  800. const_value_iterator first,
  801. const_value_iterator last) {
  802. return value_iterator(get<ObjectImpl>().erase(first.base(), last.base()));
  803. }
  804. inline dynamic::item_iterator dynamic::erase(const_item_iterator it) {
  805. return item_iterator(get<ObjectImpl>().erase(it.base()));
  806. }
  807. inline dynamic::item_iterator dynamic::erase(
  808. const_item_iterator first,
  809. const_item_iterator last) {
  810. return item_iterator(get<ObjectImpl>().erase(first.base(), last.base()));
  811. }
  812. inline void dynamic::resize(std::size_t sz, dynamic const& c) {
  813. auto& arr = get<Array>();
  814. arr.resize(sz, c);
  815. }
  816. inline void dynamic::push_back(dynamic const& v) {
  817. auto& arr = get<Array>();
  818. arr.push_back(v);
  819. }
  820. inline void dynamic::push_back(dynamic&& v) {
  821. auto& arr = get<Array>();
  822. arr.push_back(std::move(v));
  823. }
  824. inline void dynamic::pop_back() {
  825. auto& arr = get<Array>();
  826. arr.pop_back();
  827. }
  828. //////////////////////////////////////////////////////////////////////
  829. inline dynamic::dynamic(Array&& r) : type_(ARRAY) {
  830. new (&u_.array) Array(std::move(r));
  831. }
  832. #define FOLLY_DYNAMIC_DEC_TYPEINFO(T, str, val) \
  833. template <> \
  834. struct dynamic::TypeInfo<T> { \
  835. static constexpr const char* name = str; \
  836. static constexpr dynamic::Type type = val; \
  837. }; \
  838. //
  839. FOLLY_DYNAMIC_DEC_TYPEINFO(std::nullptr_t, "null", dynamic::NULLT)
  840. FOLLY_DYNAMIC_DEC_TYPEINFO(bool, "boolean", dynamic::BOOL)
  841. FOLLY_DYNAMIC_DEC_TYPEINFO(std::string, "string", dynamic::STRING)
  842. FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::Array, "array", dynamic::ARRAY)
  843. FOLLY_DYNAMIC_DEC_TYPEINFO(double, "double", dynamic::DOUBLE)
  844. FOLLY_DYNAMIC_DEC_TYPEINFO(int64_t, "int64", dynamic::INT64)
  845. FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::ObjectImpl, "object", dynamic::OBJECT)
  846. #undef FOLLY_DYNAMIC_DEC_TYPEINFO
  847. template <class T>
  848. T dynamic::asImpl() const {
  849. switch (type()) {
  850. case INT64:
  851. return to<T>(*get_nothrow<int64_t>());
  852. case DOUBLE:
  853. return to<T>(*get_nothrow<double>());
  854. case BOOL:
  855. return to<T>(*get_nothrow<bool>());
  856. case STRING:
  857. return to<T>(*get_nothrow<std::string>());
  858. default:
  859. throw_exception<TypeError>("int/double/bool/string", type());
  860. }
  861. }
  862. // Return a T* to our type, or null if we're not that type.
  863. // clang-format off
  864. template <class T>
  865. T* dynamic::get_nothrow() & noexcept {
  866. if (type_ != TypeInfo<T>::type) {
  867. return nullptr;
  868. }
  869. return getAddress<T>();
  870. }
  871. // clang-format on
  872. template <class T>
  873. T const* dynamic::get_nothrow() const& noexcept {
  874. return const_cast<dynamic*>(this)->get_nothrow<T>();
  875. }
  876. // Return T* for where we can put a T, without type checking. (Memory
  877. // might be uninitialized, even.)
  878. template <class T>
  879. T* dynamic::getAddress() noexcept {
  880. return GetAddrImpl<T>::get(u_);
  881. }
  882. template <class T>
  883. T const* dynamic::getAddress() const noexcept {
  884. return const_cast<dynamic*>(this)->getAddress<T>();
  885. }
  886. template <class T>
  887. struct dynamic::GetAddrImpl {};
  888. template <>
  889. struct dynamic::GetAddrImpl<std::nullptr_t> {
  890. static std::nullptr_t* get(Data& d) noexcept {
  891. return &d.nul;
  892. }
  893. };
  894. template <>
  895. struct dynamic::GetAddrImpl<dynamic::Array> {
  896. static Array* get(Data& d) noexcept {
  897. return &d.array;
  898. }
  899. };
  900. template <>
  901. struct dynamic::GetAddrImpl<bool> {
  902. static bool* get(Data& d) noexcept {
  903. return &d.boolean;
  904. }
  905. };
  906. template <>
  907. struct dynamic::GetAddrImpl<int64_t> {
  908. static int64_t* get(Data& d) noexcept {
  909. return &d.integer;
  910. }
  911. };
  912. template <>
  913. struct dynamic::GetAddrImpl<double> {
  914. static double* get(Data& d) noexcept {
  915. return &d.doubl;
  916. }
  917. };
  918. template <>
  919. struct dynamic::GetAddrImpl<std::string> {
  920. static std::string* get(Data& d) noexcept {
  921. return &d.string;
  922. }
  923. };
  924. template <>
  925. struct dynamic::GetAddrImpl<dynamic::ObjectImpl> {
  926. static_assert(
  927. sizeof(ObjectImpl) <= sizeof(Data::objectBuffer),
  928. "In your implementation, F14NodeMap<> apparently takes different"
  929. " amount of space depending on its template parameters. This is "
  930. "weird. Make objectBuffer bigger if you want to compile dynamic.");
  931. static ObjectImpl* get(Data& d) noexcept {
  932. void* data = &d.objectBuffer;
  933. return static_cast<ObjectImpl*>(data);
  934. }
  935. };
  936. template <class T>
  937. T& dynamic::get() {
  938. if (auto* p = get_nothrow<T>()) {
  939. return *p;
  940. }
  941. throw_exception<TypeError>(TypeInfo<T>::name, type());
  942. }
  943. template <class T>
  944. T const& dynamic::get() const {
  945. return const_cast<dynamic*>(this)->get<T>();
  946. }
  947. //////////////////////////////////////////////////////////////////////
  948. /*
  949. * Helper for implementing operator<<. Throws if the type shouldn't
  950. * support it.
  951. */
  952. template <class T>
  953. struct dynamic::PrintImpl {
  954. static void print(dynamic const&, std::ostream& out, T const& t) {
  955. out << t;
  956. }
  957. };
  958. // Otherwise, null, being (void*)0, would print as 0.
  959. template <>
  960. struct dynamic::PrintImpl<std::nullptr_t> {
  961. static void
  962. print(dynamic const& /* d */, std::ostream& out, std::nullptr_t const&) {
  963. out << "null";
  964. }
  965. };
  966. template <>
  967. struct dynamic::PrintImpl<dynamic::ObjectImpl> {
  968. static void
  969. print(dynamic const& d, std::ostream& out, dynamic::ObjectImpl const&) {
  970. d.print_as_pseudo_json(out);
  971. }
  972. };
  973. template <>
  974. struct dynamic::PrintImpl<dynamic::Array> {
  975. static void
  976. print(dynamic const& d, std::ostream& out, dynamic::Array const&) {
  977. d.print_as_pseudo_json(out);
  978. }
  979. };
  980. inline void dynamic::print(std::ostream& out) const {
  981. #define FB_X(T) PrintImpl<T>::print(*this, out, *getAddress<T>())
  982. FB_DYNAMIC_APPLY(type_, FB_X);
  983. #undef FB_X
  984. }
  985. inline std::ostream& operator<<(std::ostream& out, dynamic const& d) {
  986. d.print(out);
  987. return out;
  988. }
  989. //////////////////////////////////////////////////////////////////////
  990. // Secialization of FormatValue so dynamic objects can be formatted
  991. template <>
  992. class FormatValue<dynamic> {
  993. public:
  994. explicit FormatValue(const dynamic& val) : val_(val) {}
  995. template <class FormatCallback>
  996. void format(FormatArg& arg, FormatCallback& cb) const {
  997. switch (val_.type()) {
  998. case dynamic::NULLT:
  999. FormatValue<std::nullptr_t>(nullptr).format(arg, cb);
  1000. break;
  1001. case dynamic::BOOL:
  1002. FormatValue<bool>(val_.asBool()).format(arg, cb);
  1003. break;
  1004. case dynamic::INT64:
  1005. FormatValue<int64_t>(val_.asInt()).format(arg, cb);
  1006. break;
  1007. case dynamic::STRING:
  1008. FormatValue<std::string>(val_.asString()).format(arg, cb);
  1009. break;
  1010. case dynamic::DOUBLE:
  1011. FormatValue<double>(val_.asDouble()).format(arg, cb);
  1012. break;
  1013. case dynamic::ARRAY:
  1014. FormatValue(val_.at(arg.splitIntKey())).format(arg, cb);
  1015. break;
  1016. case dynamic::OBJECT:
  1017. FormatValue(val_.at(arg.splitKey().toString())).format(arg, cb);
  1018. break;
  1019. }
  1020. }
  1021. private:
  1022. const dynamic& val_;
  1023. };
  1024. template <class V>
  1025. class FormatValue<detail::DefaultValueWrapper<dynamic, V>> {
  1026. public:
  1027. explicit FormatValue(const detail::DefaultValueWrapper<dynamic, V>& val)
  1028. : val_(val) {}
  1029. template <class FormatCallback>
  1030. void format(FormatArg& arg, FormatCallback& cb) const {
  1031. auto& c = val_.container;
  1032. switch (c.type()) {
  1033. case dynamic::NULLT:
  1034. case dynamic::BOOL:
  1035. case dynamic::INT64:
  1036. case dynamic::STRING:
  1037. case dynamic::DOUBLE:
  1038. FormatValue<dynamic>(c).format(arg, cb);
  1039. break;
  1040. case dynamic::ARRAY: {
  1041. int key = arg.splitIntKey();
  1042. if (key >= 0 && size_t(key) < c.size()) {
  1043. FormatValue<dynamic>(c.at(key)).format(arg, cb);
  1044. } else {
  1045. FormatValue<V>(val_.defaultValue).format(arg, cb);
  1046. }
  1047. break;
  1048. }
  1049. case dynamic::OBJECT: {
  1050. auto pos = c.find(arg.splitKey());
  1051. if (pos != c.items().end()) {
  1052. FormatValue<dynamic>(pos->second).format(arg, cb);
  1053. } else {
  1054. FormatValue<V>(val_.defaultValue).format(arg, cb);
  1055. }
  1056. break;
  1057. }
  1058. }
  1059. }
  1060. private:
  1061. const detail::DefaultValueWrapper<dynamic, V>& val_;
  1062. };
  1063. } // namespace folly
  1064. #undef FB_DYNAMIC_APPLY