Skip to content

Commit

Permalink
Merge 595bb27 into eddc687
Browse files Browse the repository at this point in the history
  • Loading branch information
mdavidsaver authored Nov 21, 2023
2 parents eddc687 + 595bb27 commit e246b16
Show file tree
Hide file tree
Showing 8 changed files with 900 additions and 44 deletions.
2 changes: 2 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ INC += pvxs/unittest.h
INC += pvxs/util.h
INC += pvxs/sharedArray.h
INC += pvxs/data.h
INC += pvxs/json.h
INC += pvxs/nt.h
INC += pvxs/netcommon.h
INC += pvxs/server.h
Expand All @@ -80,6 +81,7 @@ LIB_SRCS += bitmask.cpp
LIB_SRCS += type.cpp
LIB_SRCS += data.cpp
LIB_SRCS += datafmt.cpp
LIB_SRCS += json.cpp
LIB_SRCS += pvrequest.cpp
LIB_SRCS += dataencode.cpp
LIB_SRCS += nt.cpp
Expand Down
132 changes: 94 additions & 38 deletions src/data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,33 @@ void Value::copyOut(void *ptr, StoreType type) const
break;
}
case StoreType::Null:
if(desc->id=="enum_t") {
// special case handling for NTEnum
auto index((*this).lookup("index"));
switch(type) {
case StoreType::Integer:
*reinterpret_cast<int64_t*>(ptr) = index.as<int64_t>();
return;

case StoreType::UInteger:
*reinterpret_cast<uint64_t*>(ptr) = index.as<uint64_t>();
return;

case StoreType::String: {
auto idx = index.as<uint64_t>();
auto choices = (*this).lookup("choices").as<shared_array<const std::string>>();
if(idx < choices.size()) {
*reinterpret_cast<std::string*>(ptr) = choices[idx];
return;

} else {
throw NoConvert(SB()<<"enum_t index "<<index<<" out of range for "<<choices.size());
}
}
default:
break;
}
}
break;
}

Expand Down Expand Up @@ -761,6 +788,32 @@ void Value::copyIn(const void *ptr, StoreType type)

return;
}
} else if(desc->id=="enum_t") {
auto index((*this).lookup("index"));
switch(type) {
case StoreType::Integer:
index = *reinterpret_cast<const int64_t*>(ptr);
return;
case StoreType::UInteger:
index = *reinterpret_cast<const uint64_t*>(ptr);
return;
case StoreType::String: {
auto& choice(*reinterpret_cast<const std::string*>(ptr));
auto choices((*this).lookup("choices").as<shared_array<const std::string>>());
for(auto idx : range(choices.size())) {
if(choice == choices[idx]) {
index = idx;
return;
}
}
// try to parse as string
index = parseTo<uint64_t>(choice);
return;
}
break;
default:
break;
}
}
throw NoConvert(SB()<<"Unable to assign "<<desc->code<<" with "<<type);
}
Expand Down Expand Up @@ -855,61 +908,64 @@ void Value::traverse(const std::string &expr, bool modify, bool dothrow)
// attempt to traverse to (and maybe select) member
// expect: ->[0-9a-zA-Z_]+[.\[-$]

maybedot = false;

if(expr.size()-pos >= 2 && expr[pos]=='-' && expr[pos+1]=='>') {
pos += 2; // skip past "->"

if(desc->code.code==TypeCode::Any) {
// select member of Any (may be Null)
*this = store->as<Value>();
} else if(pos>0u || desc->code.code!=TypeCode::Union) {
// expected "->"
// allow omission at the beginning of an expression when starting from a Union
store.reset();
desc = nullptr;
if(dothrow)
throw LookupError(SB()<<"expected -> in '"<<expr<<"'");
break;
}

} else {
// select member of Union
size_t sep = expr.find_first_of("<[-.", pos);
maybedot = false;

decltype (desc->mlookup)::const_iterator it;
auto& fld = store->as<Value>();
if(desc->code.code==TypeCode::Any) {
// select member of Any (may be Null)
*this = store->as<Value>();

if(sep>0 && (it=desc->mlookup.find(expr.substr(pos, sep-pos)))!=desc->mlookup.end()) {
// found it.
} else {
// select member of Union
size_t sep = expr.find_first_of("<[-.", pos);

if(modify || fld.desc==&desc->members[it->second]) {
// will select, or already selected
if(fld.desc!=&desc->members[it->second]) {
// select
std::shared_ptr<const FieldDesc> mtype(store->top->desc, &desc->members[it->second]);
fld = Value(mtype, *this);
}
pos = sep;
*this = fld;
maybedot = true;
decltype (desc->mlookup)::const_iterator it;
auto& fld = store->as<Value>();

} else {
// traversing const Value, can't select Union
store.reset();
desc = nullptr;
if(dothrow)
throw LookupError(SB()<<"traversing const Value, can't select Union in '"<<expr<<"'");
}
if(sep>0 && (it=desc->mlookup.find(expr.substr(pos, sep-pos)))!=desc->mlookup.end()) {
// found it.

} else if(fld.desc) {
// deref selected
if(modify || fld.desc==&desc->members[it->second]) {
// will select, or already selected
if(fld.desc!=&desc->members[it->second]) {
// select
std::shared_ptr<const FieldDesc> mtype(store->top->desc, &desc->members[it->second]);
fld = Value(mtype, *this);
}
pos = sep;
*this = fld;
maybedot = true;

} else {
// traversing const Value, can't select Union
store.reset();
desc = nullptr;
if(dothrow)
throw LookupError(SB()<<"can't deref. empty Union '"<<expr<<"'");
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 {
// expected "->"
store.reset();
desc = nullptr;
if(dothrow)
throw LookupError(SB()<<"expected -> in '"<<expr<<"'");
}

} else if(desc->code.isarray() && desc->code.kind()==Kind::Compound) {
Expand Down
Loading

0 comments on commit e246b16

Please sign in to comment.