allow Union deref w/o field name

This commit is contained in:
Michael Davidsaver
2020-07-16 13:50:45 -07:00
parent 38c15e655f
commit f22715063c
2 changed files with 37 additions and 3 deletions
+12 -2
View File
@@ -715,7 +715,7 @@ void Value::traverse(const std::string &expr, bool modify, bool dothrow)
maybedot = false;
if(expr.size()-pos >= 3 && expr[pos]=='-' && expr[pos+1]=='>') {
if(expr.size()-pos >= 2 && expr[pos]=='-' && expr[pos+1]=='>') {
pos += 2; // skip past "->"
if(desc->code.code==TypeCode::Any) {
@@ -727,10 +727,10 @@ void Value::traverse(const std::string &expr, bool modify, bool dothrow)
size_t sep = expr.find_first_of("<[-.", pos);
decltype (desc->mlookup)::const_iterator it;
auto& fld = store->as<Value>();
if(sep>0 && (it=desc->mlookup.find(expr.substr(pos, sep-pos)))!=desc->mlookup.end()) {
// found it.
auto& fld = store->as<Value>();
if(modify || fld.desc==&desc->members[it->second]) {
// will select, or already selected
@@ -750,6 +750,16 @@ void Value::traverse(const std::string &expr, bool modify, bool dothrow)
if(dothrow)
throw LookupError(SB()<<"traversing const Value, can't select Union in '"<<expr<<"'");
}
} else if(fld.desc) {
// deref selected
*this = fld;
} else {
store.reset();
desc = nullptr;
if(dothrow)
throw LookupError(SB()<<"can't deref. empty Union '"<<expr<<"'");
}
}
} else {
+25 -1
View File
@@ -67,6 +67,29 @@ void testAssign()
testOk1(!val["alarm"].isMarked(true, false));
}
void testAssignUnion()
{
testDiag("%s", __func__);
auto val = TypeDef(TypeCode::Union, {
members::UInt16("u16"),
members::String("s"),
}).create();
val["->u16"] = 42;
testEq(val.as<std::string>(), "42");
val["->s"] = "test";
testEq(val.as<std::string>(), "test");
testEq(val.nameOf(val["->"]), "s");
testThrows<std::invalid_argument>([&val](){
val["->u16"] = "hello";
});
//val = nullptr;
}
void testName()
{
testDiag("%s", __func__);
@@ -314,10 +337,11 @@ void testAssignSimilar()
MAIN(testdata)
{
testPlan(93);
testPlan(97);
testSetup();
testTraverse();
testAssign();
testAssignUnion();
testName();
testIterStruct();
testIterUnion();