Commit 07dc3ce5 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot 6

Deprecate dynamic::dynamic(std::initializer_list<dynamic>)

Summary:After DR95 the single braces dispatch to the copy constructor
(http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467),
so it is not possible anymore to initialize a singleton dynamic array
using the braces syntax. The initializer list constructor already had
a special case for empty lists, which unconditionally called the
default constructor if defined.

This diff deprecates the braces syntax and defines the following alternative:
```
dynamic empty = dynamic::array;
dynamic a = dynamic::array(1, 2, "foo");
```

Reviewed By: luciang, yfeldblum

Differential Revision: D3013423

fb-gh-sync-id: a0cf09dfd96e9806044f7c3bf3592c637a9bc932
shipit-source-id: a0cf09dfd96e9806044f7c3bf3592c637a9bc932
parent b873a628
...@@ -30,7 +30,9 @@ namespace folly { ...@@ -30,7 +30,9 @@ namespace folly {
* *
* Example: * Example:
* *
* dynamic d = { { 1, 2, 3 }, { 4, 5 } }; // a vector of vector of int * dynamic d = dynamic::array(
* dynamic::array(1, 2, 3),
* dynamic::array(4, 5)); // a vector of vector of int
* auto vvi = convertTo<fbvector<fbvector<int>>>(d); * auto vvi = convertTo<fbvector<fbvector<int>>>(d);
* *
* See docs/DynamicConverter.md for supported types and customization * See docs/DynamicConverter.md for supported types and customization
...@@ -319,7 +321,7 @@ struct DynamicConstructor<C, ...@@ -319,7 +321,7 @@ struct DynamicConstructor<C,
!std::is_constructible<StringPiece, const C&>::value && !std::is_constructible<StringPiece, const C&>::value &&
dynamicconverter_detail::is_range<C>::value>::type> { dynamicconverter_detail::is_range<C>::value>::type> {
static dynamic construct(const C& x) { static dynamic construct(const C& x) {
dynamic d = {}; dynamic d = dynamic::array;
for (auto& item : x) { for (auto& item : x) {
d.push_back(toDynamic(item)); d.push_back(toDynamic(item));
} }
...@@ -331,7 +333,7 @@ struct DynamicConstructor<C, ...@@ -331,7 +333,7 @@ struct DynamicConstructor<C,
template<typename A, typename B> template<typename A, typename B>
struct DynamicConstructor<std::pair<A, B>, void> { struct DynamicConstructor<std::pair<A, B>, void> {
static dynamic construct(const std::pair<A, B>& x) { static dynamic construct(const std::pair<A, B>& x) {
dynamic d = {}; dynamic d = dynamic::array;
d.push_back(toDynamic(x.first)); d.push_back(toDynamic(x.first));
d.push_back(toDynamic(x.second)); d.push_back(toDynamic(x.second));
return d; return d;
......
...@@ -26,9 +26,9 @@ folly::dynamic;` was used): ...@@ -26,9 +26,9 @@ folly::dynamic;` was used):
dynamic boolean = false; dynamic boolean = false;
// Arrays can be initialized with brackets. // Arrays can be initialized with brackets.
dynamic array = { "array ", "of ", 4, " elements" }; dynamic array = dynamic::array("array ", "of ", 4, " elements");
assert(array.size() == 4); assert(array.size() == 4);
dynamic emptyArray = {}; dynamic emptyArray = dynamic::array;
assert(emptyArray.empty()); assert(emptyArray.empty());
// Maps from dynamics to dynamics are called objects. The // Maps from dynamics to dynamics are called objects. The
...@@ -81,7 +81,7 @@ For more complicated conversions, see [DynamicConverter](DynamicConverter.md). ...@@ -81,7 +81,7 @@ For more complicated conversions, see [DynamicConverter](DynamicConverter.md).
You can iterate over dynamic arrays as you would over any C++ sequence container. You can iterate over dynamic arrays as you would over any C++ sequence container.
``` Cpp ``` Cpp
dynamic array = {2, 3, "foo"}; dynamic array = dynamic::array(2, 3, "foo");
for (auto& val : array) { for (auto& val : array) {
doSomethingWith(val); doSomethingWith(val);
...@@ -145,7 +145,7 @@ here's what it looks like: ...@@ -145,7 +145,7 @@ here's what it looks like:
// Building the same document programatically. // Building the same document programatically.
dynamic sonOfAJ = dynamic::object dynamic sonOfAJ = dynamic::object
("key", 12) ("key", 12)
("key2", { false, nullptr, true, "yay" }); ("key2", dynamic::array(false, nullptr, true, "yay"));
// Printing. (See also folly::toPrettyJson) // Printing. (See also folly::toPrettyJson)
auto str = folly::toJson(sonOfAJ); auto str = folly::toJson(sonOfAJ);
......
...@@ -189,9 +189,20 @@ private: ...@@ -189,9 +189,20 @@ private:
dynamic val_; dynamic val_;
}; };
inline void dynamic::array(EmptyArrayTag) {}
template <class... Args>
inline dynamic dynamic::array(Args&& ...args) {
return dynamic(std::initializer_list<dynamic>{std::forward<Args>(args)...},
PrivateTag());
}
// This looks like a case for perfect forwarding, but our use of // This looks like a case for perfect forwarding, but our use of
// std::initializer_list for constructing dynamic arrays makes it less // std::initializer_list for constructing dynamic arrays makes it less
// functional than doing this manually. // functional than doing this manually.
// TODO(ott, 10300209): When the initializer_list constructor is gone,
// simplify this.
inline dynamic::ObjectMaker dynamic::object() { return ObjectMaker(); } inline dynamic::ObjectMaker dynamic::object() { return ObjectMaker(); }
inline dynamic::ObjectMaker dynamic::object(dynamic&& a, dynamic&& b) { inline dynamic::ObjectMaker dynamic::object(dynamic&& a, dynamic&& b) {
return ObjectMaker(std::move(a), std::move(b)); return ObjectMaker(std::move(a), std::move(b));
...@@ -246,6 +257,12 @@ struct dynamic::const_value_iterator ...@@ -246,6 +257,12 @@ struct dynamic::const_value_iterator
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
inline dynamic::dynamic(void (*)(EmptyArrayTag))
: type_(ARRAY)
{
new (&u_.array) Array();
}
inline dynamic::dynamic(ObjectMaker (*)()) inline dynamic::dynamic(ObjectMaker (*)())
: type_(OBJECT) : type_(OBJECT)
{ {
...@@ -282,17 +299,21 @@ inline dynamic::dynamic(fbstring&& s) ...@@ -282,17 +299,21 @@ inline dynamic::dynamic(fbstring&& s)
new (&u_.string) fbstring(std::move(s)); new (&u_.string) fbstring(std::move(s));
} }
inline dynamic& dynamic::operator=(std::initializer_list<dynamic> il) { inline dynamic::dynamic(std::initializer_list<dynamic> il)
(*this) = dynamic(il); : dynamic(std::move(il), PrivateTag()) {
return *this;
} }
inline dynamic::dynamic(std::initializer_list<dynamic> il) inline dynamic::dynamic(std::initializer_list<dynamic> il, PrivateTag)
: type_(ARRAY) : type_(ARRAY)
{ {
new (&u_.array) Array(il.begin(), il.end()); new (&u_.array) Array(il.begin(), il.end());
} }
inline dynamic& dynamic::operator=(std::initializer_list<dynamic> il) {
(*this) = dynamic(il, PrivateTag());
return *this;
}
inline dynamic::dynamic(ObjectMaker&& maker) inline dynamic::dynamic(ObjectMaker&& maker)
: type_(OBJECT) : type_(OBJECT)
{ {
...@@ -596,23 +617,23 @@ inline dynamic::const_item_iterator dynamic::erase(const_item_iterator first, ...@@ -596,23 +617,23 @@ inline dynamic::const_item_iterator dynamic::erase(const_item_iterator first,
} }
inline void dynamic::resize(std::size_t sz, dynamic const& c) { inline void dynamic::resize(std::size_t sz, dynamic const& c) {
auto& array = get<Array>(); auto& arr = get<Array>();
array.resize(sz, c); arr.resize(sz, c);
} }
inline void dynamic::push_back(dynamic const& v) { inline void dynamic::push_back(dynamic const& v) {
auto& array = get<Array>(); auto& arr = get<Array>();
array.push_back(v); arr.push_back(v);
} }
inline void dynamic::push_back(dynamic&& v) { inline void dynamic::push_back(dynamic&& v) {
auto& array = get<Array>(); auto& arr = get<Array>();
array.push_back(std::move(v)); arr.push_back(std::move(v));
} }
inline void dynamic::pop_back() { inline void dynamic::pop_back() {
auto& array = get<Array>(); auto& arr = get<Array>();
array.pop_back(); arr.pop_back();
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* dynamic str = "string"; * dynamic str = "string";
* dynamic map = dynamic::object; * dynamic map = dynamic::object;
* map[str] = twelve; * map[str] = twelve;
* map[str + "another_str"] = { "array", "of", 4, "elements" }; * map[str + "another_str"] = dynamic::array("array", "of", 4, "elements");
* map.insert("null_element", nullptr); * map.insert("null_element", nullptr);
* ++map[str]; * ++map[str];
* assert(map[str] == 13); * assert(map[str] == 13);
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
* // Building a complex object with a sub array inline: * // Building a complex object with a sub array inline:
* dynamic d = dynamic::object * dynamic d = dynamic::object
* ("key", "value") * ("key", "value")
* ("key2", { "a", "array" }) * ("key2", dynamic::array("a", "array"))
* ; * ;
* *
* Also see folly/json.h for the serialization and deserialization * Also see folly/json.h for the serialization and deserialization
...@@ -118,24 +118,34 @@ public: ...@@ -118,24 +118,34 @@ public:
struct const_item_iterator; struct const_item_iterator;
/* /*
* Creation routines for making dynamic objects. Objects are maps * Creation routines for making dynamic objects and arrays. Objects
* from key to value (so named due to json-related origins here). * are maps from key to value (so named due to json-related origins
* here).
* *
* Example: * Example:
* *
* // Make a fairly complex dynamic: * // Make a fairly complex dynamic:
* dynamic d = dynamic::object("key", "value1") * dynamic d = dynamic::object("key", "value1")
* ("key2", { "value", "with", 4, "words" }); * ("key2", dynamic::array("value",
* "with",
* 4,
* "words"));
* *
* // Build an object in a few steps: * // Build an object in a few steps:
* dynamic d = dynamic::object; * dynamic d = dynamic::object;
* d["key"] = 12; * d["key"] = 12;
* d["something_else"] = { 1, 2, 3, nullptr }; * d["something_else"] = dynamic::array(1, 2, 3, nullptr);
*/ */
private: private:
struct PrivateTag {};
struct EmptyArrayTag {};
struct ObjectMaker; struct ObjectMaker;
public: public:
static void array(EmptyArrayTag);
template <class... Args>
static dynamic array(Args&& ...args);
static ObjectMaker object(); static ObjectMaker object();
static ObjectMaker object(dynamic&&, dynamic&&); static ObjectMaker object(dynamic&&, dynamic&&);
static ObjectMaker object(dynamic const&, dynamic&&); static ObjectMaker object(dynamic const&, dynamic&&);
...@@ -152,9 +162,10 @@ public: ...@@ -152,9 +162,10 @@ public:
/* implicit */ dynamic(fbstring&& val); /* implicit */ dynamic(fbstring&& val);
/* /*
* This is part of the plumbing for object(), above. Used to create * This is part of the plumbing for array() and object(), above.
* a new object dynamic. * Used to create a new array or object dynamic.
*/ */
/* implicit */ dynamic(void (*)(EmptyArrayTag));
/* implicit */ dynamic(ObjectMaker (*)()); /* implicit */ dynamic(ObjectMaker (*)());
/* implicit */ dynamic(ObjectMaker const&) = delete; /* implicit */ dynamic(ObjectMaker const&) = delete;
/* implicit */ dynamic(ObjectMaker&&); /* implicit */ dynamic(ObjectMaker&&);
...@@ -166,7 +177,14 @@ public: ...@@ -166,7 +177,14 @@ public:
* *
* dynamic v = { 1, 2, 3, "foo" }; * dynamic v = { 1, 2, 3, "foo" };
*/ */
// TODO(ott, 10300209): Remove once all uses have been eradicated.
FOLLY_DEPRECATED(
"Initializer list syntax is deprecated (#10300209). Use dynamic::array.")
/* implicit */ dynamic(std::initializer_list<dynamic> il); /* implicit */ dynamic(std::initializer_list<dynamic> il);
dynamic(std::initializer_list<dynamic> il, PrivateTag);
FOLLY_DEPRECATED(
"Initializer list syntax is deprecated (#10300209). Use dynamic::array.")
dynamic& operator=(std::initializer_list<dynamic> il); dynamic& operator=(std::initializer_list<dynamic> il);
/* /*
......
...@@ -445,7 +445,7 @@ dynamic parseArray(Input& in) { ...@@ -445,7 +445,7 @@ dynamic parseArray(Input& in) {
assert(*in == '['); assert(*in == '[');
++in; ++in;
dynamic ret = {}; dynamic ret = dynamic::array;
in.skipWhitespace(); in.skipWhitespace();
if (*in == ']') { if (*in == ']') {
......
...@@ -130,7 +130,7 @@ TEST(DynamicConverter, simple_builtins) { ...@@ -130,7 +130,7 @@ TEST(DynamicConverter, simple_builtins) {
auto i2 = convertTo<std::string>(d2); auto i2 = convertTo<std::string>(d2);
EXPECT_EQ(i2, "13"); EXPECT_EQ(i2, "13");
dynamic d3 = { 12, "Scala" }; dynamic d3 = dynamic::array(12, "Scala");
auto i3 = convertTo<std::pair<int, std::string>>(d3); auto i3 = convertTo<std::pair<int, std::string>>(d3);
EXPECT_EQ(i3.first, 12); EXPECT_EQ(i3.first, 12);
EXPECT_EQ(i3.second, "Scala"); EXPECT_EQ(i3.second, "Scala");
...@@ -142,19 +142,19 @@ TEST(DynamicConverter, simple_builtins) { ...@@ -142,19 +142,19 @@ TEST(DynamicConverter, simple_builtins) {
} }
TEST(DynamicConverter, simple_fbvector) { TEST(DynamicConverter, simple_fbvector) {
dynamic d1 = { 1, 2, 3 }; dynamic d1 = dynamic::array(1, 2, 3);
auto i1 = convertTo<folly::fbvector<int>>(d1); auto i1 = convertTo<folly::fbvector<int>>(d1);
decltype(i1) i1b = { 1, 2, 3 }; decltype(i1) i1b = { 1, 2, 3 };
EXPECT_EQ(i1, i1b); EXPECT_EQ(i1, i1b);
} }
TEST(DynamicConverter, simple_container) { TEST(DynamicConverter, simple_container) {
dynamic d1 = { 1, 2, 3 }; dynamic d1 = dynamic::array(1, 2, 3);
auto i1 = convertTo<std::vector<int>>(d1); auto i1 = convertTo<std::vector<int>>(d1);
decltype(i1) i1b = { 1, 2, 3 }; decltype(i1) i1b = { 1, 2, 3 };
EXPECT_EQ(i1, i1b); EXPECT_EQ(i1, i1b);
dynamic d2 = { 1, 3, 5, 2, 4 }; dynamic d2 = dynamic::array(1, 3, 5, 2, 4);
auto i2 = convertTo<std::set<int>>(d2); auto i2 = convertTo<std::set<int>>(d2);
decltype(i2) i2b = { 1, 2, 3, 5, 4 }; decltype(i2) i2b = { 1, 2, 3, 5, 4 };
EXPECT_EQ(i2, i2b); EXPECT_EQ(i2, i2b);
...@@ -166,7 +166,8 @@ TEST(DynamicConverter, simple_map) { ...@@ -166,7 +166,8 @@ TEST(DynamicConverter, simple_map) {
decltype(i1) i1b = { { 1, "one" }, { 2, "two" } }; decltype(i1) i1b = { { 1, "one" }, { 2, "two" } };
EXPECT_EQ(i1, i1b); EXPECT_EQ(i1, i1b);
dynamic d2 = { { 3, "three" }, { 4, "four" } }; dynamic d2 = dynamic::array(dynamic::array(3, "three"),
dynamic::array(4, "four"));
auto i2 = convertTo<std::unordered_map<int, std::string>>(d2); auto i2 = convertTo<std::unordered_map<int, std::string>>(d2);
decltype(i2) i2b = { { 3, "three" }, { 4, "four" } }; decltype(i2) i2b = { { 3, "three" }, { 4, "four" } };
EXPECT_EQ(i2, i2b); EXPECT_EQ(i2, i2b);
...@@ -178,7 +179,8 @@ TEST(DynamicConverter, map_keyed_by_string) { ...@@ -178,7 +179,8 @@ TEST(DynamicConverter, map_keyed_by_string) {
decltype(i1) i1b = { { "1", "one" }, { "2", "two" } }; decltype(i1) i1b = { { "1", "one" }, { "2", "two" } };
EXPECT_EQ(i1, i1b); EXPECT_EQ(i1, i1b);
dynamic d2 = { { "3", "three" }, { "4", "four" } }; dynamic d2 = dynamic::array(dynamic::array("3", "three"),
dynamic::array("4", "four"));
auto i2 = convertTo<std::unordered_map<std::string, std::string>>(d2); auto i2 = convertTo<std::unordered_map<std::string, std::string>>(d2);
decltype(i2) i2b = { { "3", "three" }, { "4", "four" } }; decltype(i2) i2b = { { "3", "three" }, { "4", "four" } };
EXPECT_EQ(i2, i2b); EXPECT_EQ(i2, i2b);
...@@ -193,13 +195,15 @@ TEST(DynamicConverter, map_to_vector_of_pairs) { ...@@ -193,13 +195,15 @@ TEST(DynamicConverter, map_to_vector_of_pairs) {
} }
TEST(DynamicConverter, nested_containers) { TEST(DynamicConverter, nested_containers) {
dynamic d1 = { { 1 }, { }, { 2, 3 } }; dynamic d1 = dynamic::array(dynamic::array(1),
dynamic::array(),
dynamic::array(2, 3));
auto i1 = convertTo<folly::fbvector<std::vector<uint8_t>>>(d1); auto i1 = convertTo<folly::fbvector<std::vector<uint8_t>>>(d1);
decltype(i1) i1b = { { 1 }, { }, { 2, 3 } }; decltype(i1) i1b = { { 1 }, { }, { 2, 3 } };
EXPECT_EQ(i1, i1b); EXPECT_EQ(i1, i1b);
dynamic h2a = { "3", ".", "1", "4" }; dynamic h2a = dynamic::array("3", ".", "1", "4");
dynamic h2b = { "2", ".", "7", "2" }; dynamic h2b = dynamic::array("2", ".", "7", "2");
dynamic d2 = dynamic::object(3.14, h2a)(2.72, h2b); dynamic d2 = dynamic::object(3.14, h2a)(2.72, h2b);
auto i2 = convertTo<std::map<double, std::vector<folly::fbstring>>>(d2); auto i2 = convertTo<std::map<double, std::vector<folly::fbstring>>>(d2);
decltype(i2) i2b = decltype(i2) i2b =
...@@ -224,7 +228,8 @@ TEST(DynamicConverter, custom_class) { ...@@ -224,7 +228,8 @@ TEST(DynamicConverter, custom_class) {
auto i1 = convertTo<A>(d1); auto i1 = convertTo<A>(d1);
EXPECT_EQ(i1.i, 17); EXPECT_EQ(i1.i, 17);
dynamic d2 = { dynamic::object("i", 18), dynamic::object("i", 19) }; dynamic d2 = dynamic::array(dynamic::object("i", 18),
dynamic::object("i", 19));
auto i2 = convertTo<std::vector<A>>(d2); auto i2 = convertTo<std::vector<A>>(d2);
decltype(i2) i2b = { { 18 }, { 19 } }; decltype(i2) i2b = { { 18 }, { 19 } };
EXPECT_EQ(i2, i2b); EXPECT_EQ(i2, i2b);
...@@ -255,21 +260,21 @@ TEST(DynamicConverter, crazy) { ...@@ -255,21 +260,21 @@ TEST(DynamicConverter, crazy) {
dynamic dynamic
ds1 = { "a", "e", "i", "o", "u" }, ds1 = dynamic::array("a", "e", "i", "o", "u"),
ds2 = { "2", "3", "5", "7" }, ds2 = dynamic::array("2", "3", "5", "7"),
ds3 = { "Hello", "World" }; ds3 = dynamic::array("Hello", "World");
dynamic dynamic
dv1 = {}, dv1 = dynamic::array,
dv2 = { ds1, ds2 }, dv2 = dynamic::array(ds1, ds2),
dv3({ ds3 }); dv3(dynamic::array(ds3));
dynamic dynamic
dm1 = dynamic::object(true, dv1)(false, dv2), dm1 = dynamic::object(true, dv1)(false, dv2),
dm2 = { { true, dv3 } }; dm2 = dynamic::array(dynamic::array(true, dv3));
dynamic dynamic
df1 = { dm1, dm2 }; df1 = dynamic::array(dm1, dm2);
auto i = convertTo<std::vector<std::unordered_map<bool, std::vector< auto i = convertTo<std::vector<std::unordered_map<bool, std::vector<
...@@ -296,7 +301,7 @@ TEST(DynamicConverter, consts) { ...@@ -296,7 +301,7 @@ TEST(DynamicConverter, consts) {
auto i4 = convertTo<const bool>(d4); auto i4 = convertTo<const bool>(d4);
EXPECT_EQ(true, i4); EXPECT_EQ(true, i4);
dynamic d5 = { 1, 2 }; dynamic d5 = dynamic::array(1, 2);
auto i5 = convertTo<const std::pair<const int, const int>>(d5); auto i5 = convertTo<const std::pair<const int, const int>>(d5);
decltype(i5) i5b = { 1, 2 }; decltype(i5) i5b = { 1, 2 };
EXPECT_EQ(i5b, i5); EXPECT_EQ(i5b, i5);
...@@ -334,7 +339,7 @@ TEST(DynamicConverter, construct) { ...@@ -334,7 +339,7 @@ TEST(DynamicConverter, construct) {
using std::string; using std::string;
{ {
vector<int> c { 1, 2, 3 }; vector<int> c { 1, 2, 3 };
dynamic d = { 1, 2, 3 }; dynamic d = dynamic::array(1, 2, 3);
EXPECT_EQ(d, toDynamic(c)); EXPECT_EQ(d, toDynamic(c));
} }
...@@ -352,13 +357,13 @@ TEST(DynamicConverter, construct) { ...@@ -352,13 +357,13 @@ TEST(DynamicConverter, construct) {
{ {
map<string, pair<string, int>> c { { "a", { "b", 3 } } }; map<string, pair<string, int>> c { { "a", { "b", 3 } } };
dynamic d = dynamic::object("a", dynamic { "b", 3 }); dynamic d = dynamic::object("a", dynamic::array("b", 3));
EXPECT_EQ(d, toDynamic(c)); EXPECT_EQ(d, toDynamic(c));
} }
{ {
map<string, pair<string, int>> c { { "a", { "b", 3 } } }; map<string, pair<string, int>> c { { "a", { "b", 3 } } };
dynamic d = dynamic::object("a", dynamic { "b", 3 }); dynamic d = dynamic::object("a", dynamic::array("b", 3));
EXPECT_EQ(d, toDynamic(c)); EXPECT_EQ(d, toDynamic(c));
} }
...@@ -366,7 +371,8 @@ TEST(DynamicConverter, construct) { ...@@ -366,7 +371,8 @@ TEST(DynamicConverter, construct) {
vector<int> vi { 2, 3, 4, 5 }; vector<int> vi { 2, 3, 4, 5 };
auto c = std::make_pair(range(vi.begin(), vi.begin() + 3), auto c = std::make_pair(range(vi.begin(), vi.begin() + 3),
range(vi.begin() + 1, vi.begin() + 4)); range(vi.begin() + 1, vi.begin() + 4));
dynamic d = { { 2, 3, 4 }, { 3, 4, 5 } }; dynamic d = dynamic::array(dynamic::array(2, 3, 4),
dynamic::array(3, 4, 5));
EXPECT_EQ(d, toDynamic(c)); EXPECT_EQ(d, toDynamic(c));
} }
} }
......
...@@ -30,7 +30,7 @@ using folly::TypeError; ...@@ -30,7 +30,7 @@ using folly::TypeError;
TEST(Dynamic, ArrayGenerator) { TEST(Dynamic, ArrayGenerator) {
// Make sure arrays can be used with folly::gen. // Make sure arrays can be used with folly::gen.
using namespace folly::gen; using namespace folly::gen;
dynamic arr { 1, 2, 3, 4 }; dynamic arr = dynamic::array(1, 2, 3, 4);
EXPECT_EQ(from(arr) | take(3) | member(&dynamic::asInt) | sum, 6); EXPECT_EQ(from(arr) | take(3) | member(&dynamic::asInt) | sum, 6);
} }
...@@ -102,7 +102,7 @@ TEST(Dynamic, FormattedIO) { ...@@ -102,7 +102,7 @@ TEST(Dynamic, FormattedIO) {
EXPECT_EQ(out.str(), "0xd 1e+02\n"); EXPECT_EQ(out.str(), "0xd 1e+02\n");
out.str(""); out.str("");
dynamic arrr = { 1, 2, 3 }; dynamic arrr = dynamic::array(1, 2, 3);
out << arrr; out << arrr;
EXPECT_EQ(out.str(), "[1,2,3]"); EXPECT_EQ(out.str(), "[1,2,3]");
...@@ -112,8 +112,9 @@ TEST(Dynamic, FormattedIO) { ...@@ -112,8 +112,9 @@ TEST(Dynamic, FormattedIO) {
EXPECT_EQ(out.str(), R"({"a":12})"); EXPECT_EQ(out.str(), R"({"a":12})");
out.str(""); out.str("");
dynamic objy2 = { objy, dynamic::object(12, "str"), dynamic objy2 = dynamic::array(objy,
dynamic::object(true, false) }; dynamic::object(12, "str"),
dynamic::object(true, false));
out << objy2; out << objy2;
EXPECT_EQ(out.str(), R"([{"a":12},{12:"str"},{true:false}])"); EXPECT_EQ(out.str(), R"([{"a":12},{12:"str"},{true:false}])");
} }
......
...@@ -76,7 +76,7 @@ TEST(Dynamic, ObjectBasics) { ...@@ -76,7 +76,7 @@ TEST(Dynamic, ObjectBasics) {
EXPECT_TRUE(d3 == nullptr); EXPECT_TRUE(d3 == nullptr);
d3 = dynamic::object; d3 = dynamic::object;
EXPECT_TRUE(d3.isObject()); EXPECT_TRUE(d3.isObject());
d3["foo"] = { 1, 2, 3 }; d3["foo"] = dynamic::array(1, 2, 3);
EXPECT_EQ(d3.count("foo"), 1); EXPECT_EQ(d3.count("foo"), 1);
d3[123] = 321; d3[123] = 321;
...@@ -125,7 +125,7 @@ TEST(Dynamic, ObjectBasics) { ...@@ -125,7 +125,7 @@ TEST(Dynamic, ObjectBasics) {
mergeObj1.update(mergeObj2); mergeObj1.update(mergeObj2);
EXPECT_EQ(mergeObj1, combinedPreferObj2); EXPECT_EQ(mergeObj1, combinedPreferObj2);
dynamic arr = { 1, 2, 3, 4, 5, 6 }; dynamic arr = dynamic::array(1, 2, 3, 4, 5, 6);
EXPECT_THROW(mergeObj1.update(arr), std::exception); EXPECT_THROW(mergeObj1.update(arr), std::exception);
mergeObj1 = origMergeObj1; // reset it mergeObj1 = origMergeObj1; // reset it
...@@ -161,7 +161,7 @@ TEST(Dynamic, ObjectErase) { ...@@ -161,7 +161,7 @@ TEST(Dynamic, ObjectErase) {
} }
TEST(Dynamic, ArrayErase) { TEST(Dynamic, ArrayErase) {
dynamic arr = { 1, 2, 3, 4, 5, 6 }; dynamic arr = dynamic::array(1, 2, 3, 4, 5, 6);
EXPECT_THROW(arr.erase(1), std::exception); EXPECT_THROW(arr.erase(1), std::exception);
EXPECT_EQ(arr.size(), 6); EXPECT_EQ(arr.size(), 6);
...@@ -184,7 +184,7 @@ TEST(Dynamic, StringBasics) { ...@@ -184,7 +184,7 @@ TEST(Dynamic, StringBasics) {
} }
TEST(Dynamic, ArrayBasics) { TEST(Dynamic, ArrayBasics) {
dynamic array = { 1, 2, 3 }; dynamic array = dynamic::array(1, 2, 3);
EXPECT_EQ(array.size(), 3); EXPECT_EQ(array.size(), 3);
EXPECT_EQ(array.at(0), 1); EXPECT_EQ(array.at(0), 1);
EXPECT_EQ(array.at(1), 2); EXPECT_EQ(array.at(1), 2);
...@@ -202,7 +202,7 @@ TEST(Dynamic, ArrayBasics) { ...@@ -202,7 +202,7 @@ TEST(Dynamic, ArrayBasics) {
} }
TEST(Dynamic, DeepCopy) { TEST(Dynamic, DeepCopy) {
dynamic val = { "foo", "bar", { "foo1", "bar1" } }; dynamic val = dynamic::array("foo", "bar", dynamic::array("foo1", "bar1"));
EXPECT_EQ(val.at(2).at(0), "foo1"); EXPECT_EQ(val.at(2).at(0), "foo1");
EXPECT_EQ(val.at(2).at(1), "bar1"); EXPECT_EQ(val.at(2).at(1), "bar1");
dynamic val2 = val; dynamic val2 = val;
...@@ -217,26 +217,23 @@ TEST(Dynamic, DeepCopy) { ...@@ -217,26 +217,23 @@ TEST(Dynamic, DeepCopy) {
EXPECT_EQ(val2.at(2).at(0), "foo3"); EXPECT_EQ(val2.at(2).at(0), "foo3");
EXPECT_EQ(val2.at(2).at(1), "bar3"); EXPECT_EQ(val2.at(2).at(1), "bar3");
dynamic obj = dynamic::object("a", "b") dynamic obj =
("c", {"d", "e", "f"}) dynamic::object("a", "b")
; ("c", dynamic::array("d", "e", "f"));
EXPECT_EQ(obj.at("a"), "b"); EXPECT_EQ(obj.at("a"), "b");
dynamic obj2 = obj; dynamic obj2 = obj;
obj2.at("a") = {1, 2, 3}; obj2.at("a") = dynamic::array(1, 2, 3);
EXPECT_EQ(obj.at("a"), "b"); EXPECT_EQ(obj.at("a"), "b");
dynamic expected = {1, 2, 3}; dynamic expected = dynamic::array(1, 2, 3);
EXPECT_EQ(obj2.at("a"), expected); EXPECT_EQ(obj2.at("a"), expected);
} }
TEST(Dynamic, ArrayReassignment) { TEST(Dynamic, ArrayReassignment) {
dynamic o = 1; dynamic o = 1;
dynamic d1 = dynamic::array(o);
// After DR95 the single braces dispatch to the copy constructor.
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467
dynamic d1 = {{o}};
EXPECT_EQ(dynamic::ARRAY, d1.type()); EXPECT_EQ(dynamic::ARRAY, d1.type());
d1 = {o}; d1 = dynamic::array(o);
EXPECT_EQ(dynamic::ARRAY, d1.type()); EXPECT_EQ(dynamic::ARRAY, d1.type());
} }
...@@ -292,7 +289,7 @@ TEST(Dynamic, GetSetDefaultTest) { ...@@ -292,7 +289,7 @@ TEST(Dynamic, GetSetDefaultTest) {
dynamic d2 = dynamic::object("foo", "bar"); dynamic d2 = dynamic::object("foo", "bar");
EXPECT_EQ(d2.setDefault("foo", "quux"), "bar"); EXPECT_EQ(d2.setDefault("foo", "quux"), "bar");
d2.setDefault("bar", dynamic({})).push_back(42); d2.setDefault("bar", dynamic::array).push_back(42);
EXPECT_EQ(d2["bar"][0], 42); EXPECT_EQ(d2["bar"][0], 42);
dynamic d3 = dynamic::object, empty = dynamic::object; dynamic d3 = dynamic::object, empty = dynamic::object;
...@@ -301,7 +298,7 @@ TEST(Dynamic, GetSetDefaultTest) { ...@@ -301,7 +298,7 @@ TEST(Dynamic, GetSetDefaultTest) {
EXPECT_EQ(d3["foo"]["bar"], "baz"); EXPECT_EQ(d3["foo"]["bar"], "baz");
// we do not allow getDefault/setDefault on arrays // we do not allow getDefault/setDefault on arrays
dynamic d4 = dynamic({}); dynamic d4 = dynamic::array;
EXPECT_ANY_THROW(d4.getDefault("foo", "bar")); EXPECT_ANY_THROW(d4.getDefault("foo", "bar"));
EXPECT_ANY_THROW(d4.setDefault("foo", "bar")); EXPECT_ANY_THROW(d4.setDefault("foo", "bar"));
} }
...@@ -309,13 +306,13 @@ TEST(Dynamic, GetSetDefaultTest) { ...@@ -309,13 +306,13 @@ TEST(Dynamic, GetSetDefaultTest) {
TEST(Dynamic, ObjectForwarding) { TEST(Dynamic, ObjectForwarding) {
// Make sure dynamic::object can be constructed the same way as any // Make sure dynamic::object can be constructed the same way as any
// dynamic. // dynamic.
dynamic d = dynamic::object("asd", {"foo", "bar"}); dynamic d = dynamic::object("asd", dynamic::array("foo", "bar"));
dynamic d2 = dynamic::object("key2", {"value", "words"}) dynamic d2 = dynamic::object("key2", dynamic::array("value", "words"))
("key", "value1"); ("key", "value1");
} }
TEST(Dynamic, GetPtr) { TEST(Dynamic, GetPtr) {
dynamic array = { 1, 2, "three" }; dynamic array = dynamic::array(1, 2, "three");
EXPECT_TRUE(array.get_ptr(0)); EXPECT_TRUE(array.get_ptr(0));
EXPECT_FALSE(array.get_ptr(-1)); EXPECT_FALSE(array.get_ptr(-1));
EXPECT_FALSE(array.get_ptr(3)); EXPECT_FALSE(array.get_ptr(3));
...@@ -334,13 +331,13 @@ TEST(Dynamic, GetPtr) { ...@@ -334,13 +331,13 @@ TEST(Dynamic, GetPtr) {
} }
TEST(Dynamic, Assignment) { TEST(Dynamic, Assignment) {
const dynamic ds[] = { { 1, 2, 3 }, const dynamic ds[] = { dynamic::array(1, 2, 3),
dynamic::object("a", true), dynamic::object("a", true),
24, 24,
26.5, 26.5,
true, true,
"hello", }; "hello", };
const dynamic dd[] = { { 5, 6 }, const dynamic dd[] = { dynamic::array(5, 6),
dynamic::object("t", "T")(1, 7), dynamic::object("t", "T")(1, 7),
9000, 9000,
3.14159, 3.14159,
......
...@@ -101,14 +101,14 @@ TEST(Json, Parse) { ...@@ -101,14 +101,14 @@ TEST(Json, Parse) {
("junk", 12) ("junk", 12)
("another", 32.2) ("another", 32.2)
("a", ("a",
{ dynamic::array(
dynamic::object("a", "b") dynamic::object("a", "b")
("c", "d"), ("c", "d"),
12.5, 12.5,
"Yo Dawg", "Yo Dawg",
{ "heh" }, dynamic::array("heh"),
nullptr nullptr
} )
) )
; ;
...@@ -131,7 +131,7 @@ TEST(Json, ParseTrailingComma) { ...@@ -131,7 +131,7 @@ TEST(Json, ParseTrailingComma) {
on.allow_trailing_comma = true; on.allow_trailing_comma = true;
off.allow_trailing_comma = false; off.allow_trailing_comma = false;
dynamic arr { 1, 2 }; dynamic arr = dynamic::array(1, 2);
EXPECT_EQ(arr, parseJson("[1, 2]", on)); EXPECT_EQ(arr, parseJson("[1, 2]", on));
EXPECT_EQ(arr, parseJson("[1, 2,]", on)); EXPECT_EQ(arr, parseJson("[1, 2,]", on));
EXPECT_EQ(arr, parseJson("[1, 2, ]", on)); EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
...@@ -442,14 +442,14 @@ TEST(Json, SortKeys) { ...@@ -442,14 +442,14 @@ TEST(Json, SortKeys) {
("junk", 12) ("junk", 12)
("another", 32.2) ("another", 32.2)
("a", ("a",
{ dynamic::array(
dynamic::object("a", "b") dynamic::object("a", "b")
("c", "d"), ("c", "d"),
12.5, 12.5,
"Yo Dawg", "Yo Dawg",
{ "heh" }, dynamic::array("heh"),
nullptr nullptr
} )
) )
; ;
...@@ -480,14 +480,14 @@ TEST(Json, PrintTo) { ...@@ -480,14 +480,14 @@ TEST(Json, PrintTo) {
(0, 1) (0, 1)
(1, 2) (1, 2)
("a", ("a",
{ dynamic::array(
dynamic::object("a", "b") dynamic::object("a", "b")
("c", "d"), ("c", "d"),
12.5, 12.5,
"Yo Dawg", "Yo Dawg",
{ "heh" }, dynamic::array("heh"),
nullptr nullptr
} )
) )
; ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment