diff --git a/src/data.cpp b/src/data.cpp index dcfbb5f..59b24c8 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -373,11 +373,29 @@ void Value::traverse(const std::string &expr, bool modify) { size_t pos=0; while(desc && postop->desc.get()) + { + auto pdesc = desc - desc->parent_index; + std::shared_ptr pstore(store, store.get() - desc->offset + pdesc->offset); + store = std::move(pstore); + desc = pdesc; + pos++; + continue; + } else { + // at top + store.reset(); + desc = nullptr; + break; + } + + } if(desc->code.code==TypeCode::Struct) { // attempt traverse to member. // expect: [0-9a-zA-Z_.]+[\[-$] - size_t sep = expr.find_first_of("[-", pos); + size_t sep = expr.find_first_of("<[-", pos); decltype (desc->mlookup)::const_iterator it; @@ -409,7 +427,7 @@ void Value::traverse(const std::string &expr, bool modify) } else { // select member of Union - size_t sep = expr.find_first_of("[-.", pos); + size_t sep = expr.find_first_of("<[-.", pos); decltype (desc->mlookup)::const_iterator it; diff --git a/src/dataencode.cpp b/src/dataencode.cpp index 77d9084..c55e48a 100644 --- a/src/dataencode.cpp +++ b/src/dataencode.cpp @@ -163,6 +163,7 @@ void from_wire(Buffer& buf, TypeDeserContext& ctxt, unsigned depth) // descs may be re-allocated (invalidating previous refs.) auto& fld = ctxt.descs[index]; auto& cfld = ctxt.descs[cindex]; + cfld.parent_index = cindex-index; // update hash // TODO investigate better ways to combine hashes diff --git a/src/dataimpl.h b/src/dataimpl.h index 2141192..c7b8149 100644 --- a/src/dataimpl.h +++ b/src/dataimpl.h @@ -69,6 +69,10 @@ struct FieldDesc { // number of FieldDesc nodes which describe this node and decendents. Inclusive. always >=1 // eg. num_index+(FieldDesc*)this jumps to next sibling size_t num_index=0; + // number of FieldDesc nodes between this node and it's a parent node (if any). + // This value also appears in the parent's miter and mlookup mappings. + // Only usable when a StructTop is accessible and this!=StructTop::desc + size_t parent_index=0; TypeCode code{TypeCode::Null}; // number of FieldDesc nodes which describe this node. Inclusive. always size()>=1 diff --git a/src/type.cpp b/src/type.cpp index 2ea02c6..60655b5 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -196,6 +196,7 @@ void build_tree(std::vector& desc, const Member& node) auto& fld = desc[index]; auto& child = desc[cindex]; + child.parent_index = cindex-index; fld.hash ^= std::hash{}(cnode.name) ^ child.hash; @@ -319,8 +320,7 @@ void FieldDesc_calculate_offset(FieldDesc* const top) { top->offset = 0; uint16_t offset = 1; - size_t index = 1; - while(index < top->size()) { + for(size_t index = 1; index < top->size(); ) { auto& fld = top[index]; switch (fld.code.code) { diff --git a/test/testdata.cpp b/test/testdata.cpp index 4bdae8e..7e055e3 100644 --- a/test/testdata.cpp +++ b/test/testdata.cpp @@ -342,15 +342,35 @@ void testDeserialize2() } } +void testTraverse() +{ + auto top = nt::NTScalar{TypeCode::Int32, true}.create(); + + testOk1(!top["<"].valid()); + + { + auto top2 = top["value<"]; + testOk1(top.compareType(top2)); + testOk1(top.compareInst(top2)); + } + { + auto sevr1 = top["alarm.severity"]; + auto sevr2 = top["value