Commit 7eccc5a3 authored by Tom Jackson's avatar Tom Jackson Committed by Peter Griess

dynamic::get_ptr

Summary: For testing containment and using the value in one operation.

Test Plan: Unit tests

Reviewed By: tudorb@fb.com

FB internal diff: D986986
parent e32d53e9
......@@ -525,32 +525,53 @@ template<class K, class V> inline dynamic& dynamic::setDefault(K&& k, V&& v) {
std::forward<V>(v))).first->second;
}
inline dynamic const& dynamic::at(dynamic const& idx) const {
return const_cast<dynamic*>(this)->at(idx);
inline dynamic* dynamic::get_ptr(dynamic const& idx) {
return const_cast<dynamic*>(const_cast<dynamic const*>(this)->get_ptr(idx));
}
inline dynamic& dynamic::at(dynamic const& idx) {
if (!isObject() && !isArray()) {
inline const dynamic* dynamic::get_ptr(dynamic const& idx) const {
if (auto* parray = get_nothrow<Array>()) {
if (!idx.isInt()) {
throw TypeError("int64", idx.type());
}
if (idx >= parray->size()) {
return nullptr;
}
return &(*parray)[idx.asInt()];
} else if (auto* pobject = get_nothrow<ObjectImpl>()) {
auto it = pobject->find(idx);
if (it == pobject->end()) {
return nullptr;
}
return &it->second;
} else {
throw TypeError("object/array", type());
}
}
inline dynamic& dynamic::at(dynamic const& idx) {
return const_cast<dynamic&>(const_cast<dynamic const*>(this)->at(idx));
}
inline dynamic const& dynamic::at(dynamic const& idx) const {
if (auto* parray = get_nothrow<Array>()) {
if (idx >= parray->size()) {
throw std::out_of_range("out of range in dynamic array");
}
if (!idx.isInt()) {
throw TypeError("int64", idx.type());
}
return (*parray)[idx.asInt()];
if (idx >= parray->size()) {
throw std::out_of_range("out of range in dynamic array");
}
assert(get_nothrow<ObjectImpl>());
auto it = find(idx);
if (it == items().end()) {
return (*parray)[idx.asInt()];
} else if (auto* pobject = get_nothrow<ObjectImpl>()) {
auto it = pobject->find(idx);
if (it == pobject->end()) {
throw std::out_of_range(to<std::string>(
"couldn't find key ", idx.asString(), " in dynamic object"));
}
return const_cast<dynamic&>(it->second);
return it->second;
} else {
throw TypeError("object/array", type());
}
}
inline bool dynamic::empty() const {
......
......@@ -316,6 +316,7 @@ public:
*/
const_item_iterator find(dynamic const&) const;
/*
* If this is an object, returns whether it contains a field with
* the given name. Otherwise throws TypeError.
......@@ -333,6 +334,20 @@ public:
dynamic const& at(dynamic const&) const;
dynamic& at(dynamic const&);
/*
* Like 'at', above, except it returns either a pointer to the contained
* object or nullptr if it wasn't found. This allows a key to be tested for
* containment and retrieved in one operation. Example:
*
* if (auto* found = d.get_ptr(key))
* // use *found;
*
* Using these with dynamic objects that are not arrays or objects
* will throw a TypeError.
*/
const dynamic* get_ptr(dynamic const&) const;
dynamic* get_ptr(dynamic const&);
/*
* This works for access to both objects and arrays.
*
......
......@@ -14,12 +14,13 @@
* limitations under the License.
*/
#include "folly/dynamic.h"
#include "folly/json.h"
#include <gtest/gtest.h>
#include <gflags/gflags.h>
#include <boost/next_prior.hpp>
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include "folly/Benchmark.h"
#include "folly/dynamic.h"
#include "folly/json.h"
using folly::dynamic;
......@@ -271,6 +272,24 @@ TEST(Dynamic, ObjectForwarding) {
("key", "value1");
}
TEST(Dynamic, GetPtr) {
dynamic array = { 1, 2, "three" };
EXPECT_TRUE(array.get_ptr(0));
EXPECT_FALSE(array.get_ptr(3));
EXPECT_EQ(dynamic("three"), *array.get_ptr(2));
const dynamic& carray = array;
EXPECT_EQ(dynamic("three"), *carray.get_ptr(2));
dynamic object = dynamic::object("one", 1)("two", 2);
EXPECT_TRUE(object.get_ptr("one"));
EXPECT_FALSE(object.get_ptr("three"));
EXPECT_EQ(dynamic(2), *object.get_ptr("two"));
*object.get_ptr("one") = 11;
EXPECT_EQ(dynamic(11), *object.get_ptr("one"));
const dynamic& cobject = object;
EXPECT_EQ(dynamic(2), *cobject.get_ptr("two"));
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);
......
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