dynamic.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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. /**
  17. * This is a runtime dynamically typed value. It holds types from a
  18. * specific predetermined set of types (ints, bools, arrays, etc). In
  19. * particular, it can be used as a convenient in-memory representation
  20. * for complete json objects.
  21. *
  22. * In general you can try to use these objects as if they were the
  23. * type they represent (although in some cases with a slightly less
  24. * complete interface than the raw type), and it'll just throw a
  25. * TypeError if it is used in an illegal way.
  26. *
  27. * Some examples:
  28. *
  29. * dynamic twelve = 12;
  30. * dynamic str = "string";
  31. * dynamic map = dynamic::object;
  32. * map[str] = twelve;
  33. * map[str + "another_str"] = dynamic::array("array", "of", 4, "elements");
  34. * map.insert("null_element", nullptr);
  35. * ++map[str];
  36. * assert(map[str] == 13);
  37. *
  38. * // Building a complex object with a sub array inline:
  39. * dynamic d = dynamic::object
  40. * ("key", "value")
  41. * ("key2", dynamic::array("a", "array"))
  42. * ;
  43. *
  44. * Also see folly/json.h for the serialization and deserialization
  45. * functions for JSON.
  46. *
  47. * Additional documentation is in folly/docs/Dynamic.md.
  48. *
  49. * @author Jordan DeLong <delong.j@fb.com>
  50. */
  51. #pragma once
  52. #include <cstdint>
  53. #include <memory>
  54. #include <ostream>
  55. #include <string>
  56. #include <type_traits>
  57. #include <utility>
  58. #include <vector>
  59. #include <boost/operators.hpp>
  60. #include <folly/Range.h>
  61. #include <folly/Traits.h>
  62. #include <folly/container/F14Map.h>
  63. #include <folly/json_pointer.h>
  64. namespace folly {
  65. //////////////////////////////////////////////////////////////////////
  66. struct dynamic;
  67. struct TypeError;
  68. //////////////////////////////////////////////////////////////////////
  69. struct dynamic : private boost::operators<dynamic> {
  70. enum Type {
  71. NULLT,
  72. ARRAY,
  73. BOOL,
  74. DOUBLE,
  75. INT64,
  76. OBJECT,
  77. STRING,
  78. };
  79. template <class T, class Enable = void>
  80. struct NumericTypeHelper;
  81. /*
  82. * We support direct iteration of arrays, and indirect iteration of objects.
  83. * See begin(), end(), keys(), values(), and items() for more.
  84. *
  85. * Array iterators dereference as the elements in the array.
  86. * Object key iterators dereference as the keys in the object.
  87. * Object value iterators dereference as the values in the object.
  88. * Object item iterators dereference as pairs of (key, value).
  89. */
  90. private:
  91. typedef std::vector<dynamic> Array;
  92. /*
  93. * Violating spec, std::vector<bool>::const_reference is not bool in libcpp:
  94. * http://howardhinnant.github.io/onvectorbool.html
  95. *
  96. * This is used to add a public ctor which is only enabled under libcpp taking
  97. * std::vector<bool>::const_reference without using the preprocessor.
  98. */
  99. struct VectorBoolConstRefFake : std::false_type {};
  100. using VectorBoolConstRefCtorType = std::conditional_t<
  101. std::is_same<std::vector<bool>::const_reference, bool>::value,
  102. VectorBoolConstRefFake,
  103. std::vector<bool>::const_reference>;
  104. public:
  105. typedef Array::iterator iterator;
  106. typedef Array::const_iterator const_iterator;
  107. typedef dynamic value_type;
  108. struct const_key_iterator;
  109. struct const_value_iterator;
  110. struct const_item_iterator;
  111. struct value_iterator;
  112. struct item_iterator;
  113. /*
  114. * Creation routines for making dynamic objects and arrays. Objects
  115. * are maps from key to value (so named due to json-related origins
  116. * here).
  117. *
  118. * Example:
  119. *
  120. * // Make a fairly complex dynamic:
  121. * dynamic d = dynamic::object("key", "value1")
  122. * ("key2", dynamic::array("value",
  123. * "with",
  124. * 4,
  125. * "words"));
  126. *
  127. * // Build an object in a few steps:
  128. * dynamic d = dynamic::object;
  129. * d["key"] = 12;
  130. * d["something_else"] = dynamic::array(1, 2, 3, nullptr);
  131. */
  132. private:
  133. struct EmptyArrayTag {};
  134. struct ObjectMaker;
  135. public:
  136. static void array(EmptyArrayTag);
  137. template <class... Args>
  138. static dynamic array(Args&&... args);
  139. static ObjectMaker object();
  140. static ObjectMaker object(dynamic, dynamic);
  141. /**
  142. * Default constructor, initializes with nullptr.
  143. */
  144. dynamic();
  145. /*
  146. * String compatibility constructors.
  147. */
  148. /* implicit */ dynamic(std::nullptr_t);
  149. /* implicit */ dynamic(StringPiece val);
  150. /* implicit */ dynamic(char const* val);
  151. /* implicit */ dynamic(std::string val);
  152. /*
  153. * This is part of the plumbing for array() and object(), above.
  154. * Used to create a new array or object dynamic.
  155. */
  156. /* implicit */ dynamic(void (*)(EmptyArrayTag));
  157. /* implicit */ dynamic(ObjectMaker (*)());
  158. /* implicit */ dynamic(ObjectMaker const&) = delete;
  159. /* implicit */ dynamic(ObjectMaker&&);
  160. /*
  161. * Constructors for integral and float types.
  162. * Other types are SFINAEd out with NumericTypeHelper.
  163. */
  164. template <class T, class NumericType = typename NumericTypeHelper<T>::type>
  165. /* implicit */ dynamic(T t);
  166. /*
  167. * If v is vector<bool>, v[idx] is a proxy object implicitly convertible to
  168. * bool. Calling a function f(dynamic) with f(v[idx]) would require a double
  169. * implicit conversion (reference -> bool -> dynamic) which is not allowed,
  170. * hence we explicitly accept the reference proxy.
  171. */
  172. /* implicit */ dynamic(std::vector<bool>::reference val);
  173. /* implicit */ dynamic(VectorBoolConstRefCtorType val);
  174. /*
  175. * Create a dynamic that is an array of the values from the supplied
  176. * iterator range.
  177. */
  178. template <class Iterator>
  179. explicit dynamic(Iterator first, Iterator last);
  180. dynamic(dynamic const&);
  181. dynamic(dynamic&&) noexcept;
  182. ~dynamic() noexcept;
  183. /*
  184. * "Deep" equality comparison. This will compare all the way down
  185. * an object or array, and is potentially expensive.
  186. */
  187. bool operator==(dynamic const& o) const;
  188. /*
  189. * For all types except object this returns the natural ordering on
  190. * those types. For objects, we throw TypeError.
  191. */
  192. bool operator<(dynamic const& o) const;
  193. /*
  194. * General operators.
  195. *
  196. * These throw TypeError when used with types or type combinations
  197. * that don't support them.
  198. *
  199. * These functions may also throw if you use 64-bit integers with
  200. * doubles when the integers are too big to fit in a double.
  201. */
  202. dynamic& operator+=(dynamic const&);
  203. dynamic& operator-=(dynamic const&);
  204. dynamic& operator*=(dynamic const&);
  205. dynamic& operator/=(dynamic const&);
  206. dynamic& operator%=(dynamic const&);
  207. dynamic& operator|=(dynamic const&);
  208. dynamic& operator&=(dynamic const&);
  209. dynamic& operator^=(dynamic const&);
  210. dynamic& operator++();
  211. dynamic& operator--();
  212. /*
  213. * Assignment from other dynamics. Because of the implicit conversion
  214. * to dynamic from its potential types, you can use this to change the
  215. * type pretty intuitively.
  216. *
  217. * Basic guarantee only.
  218. */
  219. dynamic& operator=(dynamic const&);
  220. dynamic& operator=(dynamic&&) noexcept;
  221. /*
  222. * For simple dynamics (not arrays or objects), this prints the
  223. * value to an std::ostream in the expected way. Respects the
  224. * formatting manipulators that have been sent to the stream
  225. * already.
  226. *
  227. * If the dynamic holds an object or array, this prints them in a
  228. * format very similar to JSON. (It will in fact actually be JSON
  229. * as long as the dynamic validly represents a JSON object---i.e. it
  230. * can't have non-string keys.)
  231. */
  232. friend std::ostream& operator<<(std::ostream&, dynamic const&);
  233. /*
  234. * Returns true if this dynamic is of the specified type.
  235. */
  236. bool isString() const;
  237. bool isObject() const;
  238. bool isBool() const;
  239. bool isNull() const;
  240. bool isArray() const;
  241. bool isDouble() const;
  242. bool isInt() const;
  243. /*
  244. * Returns: isInt() || isDouble().
  245. */
  246. bool isNumber() const;
  247. /*
  248. * Returns the type of this dynamic.
  249. */
  250. Type type() const;
  251. /*
  252. * Returns the type of this dynamic as a printable string.
  253. */
  254. const char* typeName() const;
  255. /*
  256. * Extract a value while trying to convert to the specified type.
  257. * Throws exceptions if we cannot convert from the real type to the
  258. * requested type.
  259. *
  260. * Note you can only use this to access integral types or strings,
  261. * since arrays and objects are generally best dealt with as a
  262. * dynamic.
  263. */
  264. std::string asString() const;
  265. double asDouble() const;
  266. int64_t asInt() const;
  267. bool asBool() const;
  268. /*
  269. * Extract the value stored in this dynamic without type conversion.
  270. *
  271. * These will throw a TypeError if the dynamic has a different type.
  272. */
  273. const std::string& getString() const&;
  274. double getDouble() const&;
  275. int64_t getInt() const&;
  276. bool getBool() const&;
  277. std::string& getString() &;
  278. double& getDouble() &;
  279. int64_t& getInt() &;
  280. bool& getBool() &;
  281. std::string&& getString() &&;
  282. double getDouble() &&;
  283. int64_t getInt() &&;
  284. bool getBool() &&;
  285. /*
  286. * It is occasionally useful to access a string's internal pointer
  287. * directly, without the type conversion of `asString()`.
  288. *
  289. * These will throw a TypeError if the dynamic is not a string.
  290. */
  291. const char* data() const&;
  292. const char* data() && = delete;
  293. const char* c_str() const&;
  294. const char* c_str() && = delete;
  295. StringPiece stringPiece() const;
  296. /*
  297. * Returns: true if this dynamic is null, an empty array, an empty
  298. * object, or an empty string.
  299. */
  300. bool empty() const;
  301. /*
  302. * If this is an array or an object, returns the number of elements
  303. * contained. If it is a string, returns the length. Otherwise
  304. * throws TypeError.
  305. */
  306. std::size_t size() const;
  307. /*
  308. * You can iterate over the values of the array. Calling these on
  309. * non-arrays will throw a TypeError.
  310. */
  311. const_iterator begin() const;
  312. const_iterator end() const;
  313. iterator begin();
  314. iterator end();
  315. private:
  316. /*
  317. * Helper object returned by keys(), values(), and items().
  318. */
  319. template <class T>
  320. struct IterableProxy;
  321. /*
  322. * Helper for heterogeneous lookup and mutation on objects: at(), find(),
  323. * count(), erase(), operator[]
  324. */
  325. template <typename K, typename T>
  326. using IfIsNonStringDynamicConvertible = std::enable_if_t<
  327. !std::is_convertible<K, StringPiece>::value &&
  328. std::is_convertible<K, dynamic>::value,
  329. T>;
  330. public:
  331. /*
  332. * You can iterate over the keys, values, or items (std::pair of key and
  333. * value) in an object. Calling these on non-objects will throw a TypeError.
  334. */
  335. IterableProxy<const_key_iterator> keys() const;
  336. IterableProxy<const_value_iterator> values() const;
  337. IterableProxy<const_item_iterator> items() const;
  338. IterableProxy<value_iterator> values();
  339. IterableProxy<item_iterator> items();
  340. /*
  341. * AssociativeContainer-style find interface for objects. Throws if
  342. * this is not an object.
  343. *
  344. * Returns: items().end() if the key is not present, or a
  345. * const_item_iterator pointing to the item.
  346. */
  347. template <typename K>
  348. IfIsNonStringDynamicConvertible<K, const_item_iterator> find(K&&) const;
  349. template <typename K>
  350. IfIsNonStringDynamicConvertible<K, item_iterator> find(K&&);
  351. const_item_iterator find(StringPiece) const;
  352. item_iterator find(StringPiece);
  353. /*
  354. * If this is an object, returns whether it contains a field with
  355. * the given name. Otherwise throws TypeError.
  356. */
  357. template <typename K>
  358. IfIsNonStringDynamicConvertible<K, std::size_t> count(K&&) const;
  359. std::size_t count(StringPiece) const;
  360. /*
  361. * For objects or arrays, provides access to sub-fields by index or
  362. * field name.
  363. *
  364. * Using these with dynamic objects that are not arrays or objects
  365. * will throw a TypeError. Using an index that is out of range or
  366. * object-element that's not present throws std::out_of_range.
  367. */
  368. private:
  369. dynamic const& atImpl(dynamic const&) const&;
  370. public:
  371. template <typename K>
  372. IfIsNonStringDynamicConvertible<K, dynamic const&> at(K&&) const&;
  373. template <typename K>
  374. IfIsNonStringDynamicConvertible<K, dynamic&> at(K&&) &;
  375. template <typename K>
  376. IfIsNonStringDynamicConvertible<K, dynamic&&> at(K&&) &&;
  377. dynamic const& at(StringPiece) const&;
  378. dynamic& at(StringPiece) &;
  379. dynamic&& at(StringPiece) &&;
  380. /*
  381. * Locate element using JSON pointer, per RFC 6901. Returns nullptr if
  382. * element could not be located. Throws if pointer does not match the
  383. * shape of the document, e.g. uses string to index in array.
  384. */
  385. const dynamic* get_ptr(json_pointer const&) const&;
  386. dynamic* get_ptr(json_pointer const&) &;
  387. const dynamic* get_ptr(json_pointer const&) const&& = delete;
  388. dynamic* get_ptr(json_pointer const&) && = delete;
  389. /*
  390. * Like 'at', above, except it returns either a pointer to the contained
  391. * object or nullptr if it wasn't found. This allows a key to be tested for
  392. * containment and retrieved in one operation. Example:
  393. *
  394. * if (auto* found = d.get_ptr(key))
  395. * // use *found;
  396. *
  397. * Using these with dynamic objects that are not arrays or objects
  398. * will throw a TypeError.
  399. */
  400. private:
  401. const dynamic* get_ptrImpl(dynamic const&) const&;
  402. public:
  403. template <typename K>
  404. IfIsNonStringDynamicConvertible<K, const dynamic*> get_ptr(K&&) const&;
  405. template <typename K>
  406. IfIsNonStringDynamicConvertible<K, dynamic*> get_ptr(K&&) &;
  407. template <typename K>
  408. IfIsNonStringDynamicConvertible<K, dynamic*> get_ptr(K&&) && = delete;
  409. const dynamic* get_ptr(StringPiece) const&;
  410. dynamic* get_ptr(StringPiece) &;
  411. dynamic* get_ptr(StringPiece) && = delete;
  412. /*
  413. * This works for access to both objects and arrays.
  414. *
  415. * In the case of an array, the index must be an integer, and this
  416. * will throw std::out_of_range if it is less than zero or greater
  417. * than size().
  418. *
  419. * In the case of an object, the non-const overload inserts a null
  420. * value if the key isn't present. The const overload will throw
  421. * std::out_of_range if the key is not present.
  422. *
  423. * These functions do not invalidate iterators except when a null value
  424. * is inserted into an object as described above.
  425. */
  426. template <typename K>
  427. IfIsNonStringDynamicConvertible<K, dynamic&> operator[](K&&) &;
  428. template <typename K>
  429. IfIsNonStringDynamicConvertible<K, dynamic const&> operator[](K&&) const&;
  430. template <typename K>
  431. IfIsNonStringDynamicConvertible<K, dynamic&&> operator[](K&&) &&;
  432. dynamic& operator[](StringPiece) &;
  433. dynamic const& operator[](StringPiece) const&;
  434. dynamic&& operator[](StringPiece) &&;
  435. /*
  436. * Only defined for objects, throws TypeError otherwise.
  437. *
  438. * getDefault will return the value associated with the supplied key, the
  439. * supplied default otherwise. setDefault will set the key to the supplied
  440. * default if it is not yet set, otherwise leaving it. setDefault returns
  441. * a reference to the existing value if present, the new value otherwise.
  442. */
  443. template <typename K>
  444. IfIsNonStringDynamicConvertible<K, dynamic> getDefault(
  445. K&& k,
  446. const dynamic& v = dynamic::object) const&;
  447. template <typename K>
  448. IfIsNonStringDynamicConvertible<K, dynamic> getDefault(K&& k, dynamic&& v)
  449. const&;
  450. template <typename K>
  451. IfIsNonStringDynamicConvertible<K, dynamic> getDefault(
  452. K&& k,
  453. const dynamic& v = dynamic::object) &&;
  454. template <typename K>
  455. IfIsNonStringDynamicConvertible<K, dynamic> getDefault(K&& k, dynamic&& v) &&;
  456. dynamic getDefault(StringPiece k, const dynamic& v = dynamic::object) const&;
  457. dynamic getDefault(StringPiece k, dynamic&& v) const&;
  458. dynamic getDefault(StringPiece k, const dynamic& v = dynamic::object) &&;
  459. dynamic getDefault(StringPiece k, dynamic&& v) &&;
  460. template <typename K, typename V>
  461. IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(K&& k, V&& v);
  462. template <typename V>
  463. dynamic& setDefault(StringPiece k, V&& v);
  464. // MSVC 2015 Update 3 needs these extra overloads because if V were a
  465. // defaulted template parameter, it causes MSVC to consider v an rvalue
  466. // reference rather than a universal reference, resulting in it not being
  467. // able to find the correct overload to construct a dynamic with.
  468. template <typename K>
  469. IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(K&& k, dynamic&& v);
  470. template <typename K>
  471. IfIsNonStringDynamicConvertible<K, dynamic&> setDefault(
  472. K&& k,
  473. const dynamic& v = dynamic::object);
  474. dynamic& setDefault(StringPiece k, dynamic&& v);
  475. dynamic& setDefault(StringPiece k, const dynamic& v = dynamic::object);
  476. /*
  477. * Resizes an array so it has at n elements, using the supplied
  478. * default to fill new elements. Throws TypeError if this dynamic
  479. * is not an array.
  480. *
  481. * May invalidate iterators.
  482. *
  483. * Post: size() == n
  484. */
  485. void resize(std::size_t n, dynamic const& = nullptr);
  486. /*
  487. * Inserts the supplied key-value pair to an object, or throws if
  488. * it's not an object. If the key already exists, insert will overwrite the
  489. * value, i.e., similar to insert_or_assign.
  490. *
  491. * Invalidates iterators.
  492. */
  493. template <class K, class V>
  494. void insert(K&&, V&& val);
  495. /*
  496. * These functions merge two folly dynamic objects.
  497. * The "update" and "update_missing" functions extend the object by
  498. * inserting the key/value pairs of mergeObj into the current object.
  499. * For update, if key is duplicated between the two objects, it
  500. * will overwrite with the value of the object being inserted (mergeObj).
  501. * For "update_missing", it will prefer the value in the original object
  502. *
  503. * The "merge" function creates a new object consisting of the key/value
  504. * pairs of both mergeObj1 and mergeObj2
  505. * If the key is duplicated between the two objects,
  506. * it will prefer value in the second object (mergeObj2)
  507. */
  508. void update(const dynamic& mergeObj);
  509. void update_missing(const dynamic& other);
  510. static dynamic merge(const dynamic& mergeObj1, const dynamic& mergeObj2);
  511. /*
  512. * Implement recursive version of RFC7386: JSON merge patch. This modifies
  513. * the current object.
  514. */
  515. void merge_patch(const dynamic& patch);
  516. /*
  517. * Computes JSON merge patch (RFC7386) needed to mutate from source to target
  518. */
  519. static dynamic merge_diff(const dynamic& source, const dynamic& target);
  520. /*
  521. * Erase an element from a dynamic object, by key.
  522. *
  523. * Invalidates iterators to the element being erased.
  524. *
  525. * Returns the number of elements erased (i.e. 1 or 0).
  526. */
  527. template <typename K>
  528. IfIsNonStringDynamicConvertible<K, std::size_t> erase(K&&);
  529. std::size_t erase(StringPiece);
  530. /*
  531. * Erase an element from a dynamic object or array, using an
  532. * iterator or an iterator range.
  533. *
  534. * In arrays, invalidates iterators to elements after the element
  535. * being erased. In objects, invalidates iterators to the elements
  536. * being erased.
  537. *
  538. * Returns a new iterator to the first element beyond any elements
  539. * removed, or end() if there are none. (The iteration order does
  540. * not change.)
  541. */
  542. iterator erase(const_iterator it);
  543. iterator erase(const_iterator first, const_iterator last);
  544. const_key_iterator erase(const_key_iterator it);
  545. const_key_iterator erase(const_key_iterator first, const_key_iterator last);
  546. value_iterator erase(const_value_iterator it);
  547. value_iterator erase(const_value_iterator first, const_value_iterator last);
  548. item_iterator erase(const_item_iterator it);
  549. item_iterator erase(const_item_iterator first, const_item_iterator last);
  550. /*
  551. * Append elements to an array. If this is not an array, throws
  552. * TypeError.
  553. *
  554. * Invalidates iterators.
  555. */
  556. void push_back(dynamic const&);
  557. void push_back(dynamic&&);
  558. /*
  559. * Remove an element from the back of an array. If this is not an array,
  560. * throws TypeError.
  561. *
  562. * Does not invalidate iterators.
  563. */
  564. void pop_back();
  565. /*
  566. * Get a hash code. This function is called by a std::hash<>
  567. * specialization, also.
  568. *
  569. * Throws TypeError if this is an object, array, or null.
  570. */
  571. std::size_t hash() const;
  572. private:
  573. friend struct TypeError;
  574. struct ObjectImpl;
  575. template <class T>
  576. struct TypeInfo;
  577. template <class T>
  578. struct CompareOp;
  579. template <class T>
  580. struct GetAddrImpl;
  581. template <class T>
  582. struct PrintImpl;
  583. explicit dynamic(Array&& array);
  584. template <class T>
  585. T const& get() const;
  586. template <class T>
  587. T& get();
  588. // clang-format off
  589. template <class T>
  590. T* get_nothrow() & noexcept;
  591. // clang-format on
  592. template <class T>
  593. T const* get_nothrow() const& noexcept;
  594. // clang-format off
  595. template <class T>
  596. T* get_nothrow() && noexcept = delete;
  597. // clang-format on
  598. template <class T>
  599. T* getAddress() noexcept;
  600. template <class T>
  601. T const* getAddress() const noexcept;
  602. template <class T>
  603. T asImpl() const;
  604. static char const* typeName(Type);
  605. void destroy() noexcept;
  606. void print(std::ostream&) const;
  607. void print_as_pseudo_json(std::ostream&) const; // see json.cpp
  608. private:
  609. Type type_;
  610. union Data {
  611. explicit Data() : nul(nullptr) {}
  612. ~Data() {}
  613. std::nullptr_t nul;
  614. Array array;
  615. bool boolean;
  616. double doubl;
  617. int64_t integer;
  618. std::string string;
  619. /*
  620. * Objects are placement new'd here. We have to use a char buffer
  621. * because we don't know the type here (F14NodeMap<> with
  622. * dynamic would be parameterizing a std:: template with an
  623. * incomplete type right now). (Note that in contrast we know it
  624. * is ok to do this with fbvector because we own it.)
  625. */
  626. std::aligned_storage<
  627. sizeof(F14NodeMap<int, int>),
  628. alignof(F14NodeMap<int, int>)>::type objectBuffer;
  629. } u_;
  630. };
  631. //////////////////////////////////////////////////////////////////////
  632. } // namespace folly
  633. #include <folly/dynamic-inl.h>