new (&u_.string) fbstring(std::move(s));
}
+inline dynamic& dynamic::operator=(std::initializer_list<dynamic> il) {
+ (*this) = dynamic(il);
+ return *this;
+}
+
inline dynamic::dynamic(std::initializer_list<dynamic> il)
: type_(ARRAY)
{
inline int64_t dynamic::asInt() const { return asImpl<int64_t>(); }
inline bool dynamic::asBool() const { return asImpl<bool>(); }
-inline const fbstring& dynamic::getString() const { return get<fbstring>(); }
-inline double dynamic::getDouble() const { return get<double>(); }
-inline int64_t dynamic::getInt() const { return get<int64_t>(); }
-inline bool dynamic::getBool() const { return get<bool>(); }
+inline const fbstring& dynamic::getString() const& { return get<fbstring>(); }
+inline double dynamic::getDouble() const& { return get<double>(); }
+inline int64_t dynamic::getInt() const& { return get<int64_t>(); }
+inline bool dynamic::getBool() const& { return get<bool>(); }
+
+inline fbstring& dynamic::getString() & { return get<fbstring>(); }
+inline double& dynamic::getDouble() & { return get<double>(); }
+inline int64_t& dynamic::getInt() & { return get<int64_t>(); }
+inline bool& dynamic::getBool() & { return get<bool>(); }
-inline fbstring& dynamic::getString() { return get<fbstring>(); }
-inline double& dynamic::getDouble() { return get<double>(); }
-inline int64_t& dynamic::getInt() { return get<int64_t>(); }
-inline bool& dynamic::getBool() { return get<bool>(); }
+inline fbstring dynamic::getString() && { return std::move(get<fbstring>()); }
+inline double dynamic::getDouble() && { return get<double>(); }
+inline int64_t dynamic::getInt() && { return get<int64_t>(); }
+inline bool dynamic::getBool() && { return get<bool>(); }
inline const char* dynamic::data() const& { return get<fbstring>().data(); }
inline const char* dynamic::c_str() const& { return get<fbstring>().c_str(); }
return *this;
}
-inline dynamic const& dynamic::operator[](dynamic const& idx) const {
+inline dynamic const& dynamic::operator[](dynamic const& idx) const& {
return at(idx);
}
+inline dynamic dynamic::operator[](dynamic const& idx) && {
+ return std::move((*this)[idx]);
+}
+
template<class K, class V> inline dynamic& dynamic::setDefault(K&& k, V&& v) {
auto& obj = get<ObjectImpl>();
return obj.insert(std::make_pair(std::forward<K>(k),
return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx));
}
-inline dynamic& dynamic::at(dynamic const& idx) {
+inline dynamic& dynamic::at(dynamic const& idx) & {
return const_cast<dynamic&>(const_cast<dynamic const*>(this)->at(idx));
}
+inline dynamic dynamic::at(dynamic const& idx) && {
+ return std::move(at(idx));
+}
+
inline bool dynamic::empty() const {
if (isNull()) {
return true;
rv.first->second = std::forward<V>(val);
}
+inline void dynamic::update(const dynamic& mergeObj) {
+ if (!isObject() || !mergeObj.isObject()) {
+ throw TypeError("object", type(), mergeObj.type());
+ }
+
+ for (const auto& pair : mergeObj.items()) {
+ (*this)[pair.first] = pair.second;
+ }
+}
+
+inline void dynamic::update_missing(const dynamic& mergeObj1) {
+ if (!isObject() || !mergeObj1.isObject()) {
+ throw TypeError("object", type(), mergeObj1.type());
+ }
+
+ // Only add if not already there
+ for (const auto& pair : mergeObj1.items()) {
+ if ((*this).find(pair.first) == (*this).items().end()) {
+ (*this)[pair.first] = pair.second;
+ }
+ }
+}
+
+inline dynamic dynamic::merge(
+ const dynamic& mergeObj1,
+ const dynamic& mergeObj2) {
+
+ // No checks on type needed here because they are done in update_missing
+ // Note that we do update_missing here instead of update() because
+ // it will prevent the extra writes that would occur with update()
+ auto ret = mergeObj2;
+ ret.update_missing(mergeObj1);
+ return ret;
+}
+
inline std::size_t dynamic::erase(dynamic const& key) {
auto& obj = get<ObjectImpl>();
return obj.erase(key);
//////////////////////////////////////////////////////////////////////
-template<class T> struct dynamic::TypeInfo {
- static char const name[];
- static Type const type;
-};
-
-#define FB_DEC_TYPE(T) \
- template<> char const dynamic::TypeInfo<T>::name[]; \
- template<> dynamic::Type const dynamic::TypeInfo<T>::type
+#define FOLLY_DYNAMIC_DEC_TYPEINFO(T, str, val) \
+ template <> struct dynamic::TypeInfo<T> { \
+ static constexpr const char* name = str; \
+ static constexpr dynamic::Type type = val; \
+ }; \
+ //
-FB_DEC_TYPE(void*);
-FB_DEC_TYPE(bool);
-FB_DEC_TYPE(fbstring);
-FB_DEC_TYPE(dynamic::Array);
-FB_DEC_TYPE(double);
-FB_DEC_TYPE(int64_t);
-FB_DEC_TYPE(dynamic::ObjectImpl);
+FOLLY_DYNAMIC_DEC_TYPEINFO(void*, "null", dynamic::NULLT)
+FOLLY_DYNAMIC_DEC_TYPEINFO(bool, "boolean", dynamic::BOOL)
+FOLLY_DYNAMIC_DEC_TYPEINFO(fbstring, "string", dynamic::STRING)
+FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::Array, "array", dynamic::ARRAY)
+FOLLY_DYNAMIC_DEC_TYPEINFO(double, "double", dynamic::DOUBLE)
+FOLLY_DYNAMIC_DEC_TYPEINFO(int64_t, "int64", dynamic::INT64)
+FOLLY_DYNAMIC_DEC_TYPEINFO(dynamic::ObjectImpl, "object", dynamic::OBJECT)
-#undef FB_DEC_TYPE
+#undef FOLLY_DYNAMIC_DEC_TYPEINFO
template<class T>
T dynamic::asImpl() const {
out << t;
}
};
+// Otherwise, null, being (void*)0, would print as 0.
+template <>
+struct dynamic::PrintImpl<void*> {
+ static void print(dynamic const& d, std::ostream& out, void* const& nul) {
+ DCHECK_EQ((void*)0, nul);
+ out << "null";
+ }
+};
template<>
struct dynamic::PrintImpl<dynamic::ObjectImpl> {
static void print(dynamic const& d,