From d4f4fe970da59d734089c3d60acbd2288d5f61f6 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 27 Jan 2020 11:33:10 -0800 Subject: [PATCH] add Value::nameOf() --- src/data.cpp | 19 ++++++++++++++++++- src/pvxs/data.h | 10 ++++++++++ test/testdata.cpp | 18 +++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/data.cpp b/src/data.cpp index 0c5aaf6..1b3d20b 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -288,6 +288,24 @@ bool Value::idStartsWith(const std::string& prefix) const return ID.size()>=prefix.size() && prefix==ID.substr(0u, prefix.size()); } +const std::string &Value::nameOf(const Value& decendent) const +{ + if(!store || !decendent.store) + throw NoField(); + auto pidx = store->index(); + auto didx = decendent.store->index(); + if(pidx >= didx || didx >= store->top->members.size()) + throw std::logic_error("not a decendent"); + + // inefficient, but we don't keep a reverse mapping + for(auto& it : desc->mlookup) { + if(it.second == didx-pidx) + return it.first; + } + + throw std::logic_error("missing decendent"); +} + namespace { // C-style cast between scalar storage types, and print to string (base 10) template @@ -796,7 +814,6 @@ FieldStorage::~FieldStorage() size_t FieldStorage::index() const { const size_t ret = this-top->members.data(); - assert(this==&top->members[ret]); return ret; } diff --git a/src/pvxs/data.h b/src/pvxs/data.h index a106f2d..9763901 100644 --- a/src/pvxs/data.h +++ b/src/pvxs/data.h @@ -385,6 +385,16 @@ public: // int compareValue(const Value&); inline int compareType(const Value& o) { return desc==o.desc; } + /** Return our name for a decendent field. + * @code + * Value v = ...; + * assert(v.nameOf(v["some.field"])=="some.field"); + * @endcode + * @throws NoField unless both this and decendent are valid() + * @throws std::logic_error if decendent is not actually a decendent + */ + const std::string& nameOf(const Value& decendent) const; + // access to Value's ... value // not for Struct diff --git a/test/testdata.cpp b/test/testdata.cpp index 0b0741c..20e2c22 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -445,11 +445,26 @@ void testAssign() testOk1(!val["alarm"].isMarked(true, false)); } +void testName() +{ + testDiag("%s", __func__); + + auto def = nt::NTScalar{TypeCode::String}.build(); + auto val = def.create(); + + testEq(val.nameOf(val["value"]), "value"); + testEq(val.nameOf(val["alarm.status"]), "alarm.status"); + + testThrows([&val]() { + val.nameOf(val); + }); +} + } // namespace MAIN(testdata) { - testPlan(67); + testPlan(70); testSerialize1(); testDeserialize1(); testSimpleDef(); @@ -457,6 +472,7 @@ MAIN(testdata) testDeserialize2(); testTraverse(); testAssign(); + testName(); cleanup_for_valgrind(); return testDone(); }