TypeDef append from vector<>

This commit is contained in:
Michael Davidsaver
2020-03-11 19:01:19 -07:00
parent 0fd254d520
commit ffcff28276
2 changed files with 93 additions and 33 deletions
+62 -5
View File
@@ -188,6 +188,9 @@ private:
std::vector<Member> children;
friend class TypeDef;
friend class client::detail::CommonBase;
PVXS_API
void _validate() const;
public:
struct Helper;
@@ -198,13 +201,29 @@ public:
:Member(code, name, {})
{}
//! Compound member with type ID
PVXS_API
Member(TypeCode code, const std::string& name, const std::string& id, std::initializer_list<Member> children);
Member(TypeCode code, const std::string& name, const std::string& id, std::initializer_list<Member> children)
:code(code)
,name(name)
,id(id)
,children(children.begin(), children.end())
{_validate();}
template<typename Iterable>
Member(TypeCode code, const std::string& name, const std::string& id, const Iterable& children)
:code(code)
,name(name)
,id(id)
,children(children.begin(), children.end())
{_validate();}
//! Compound member without type ID
inline
Member(TypeCode code, const std::string& name, std::initializer_list<Member> children)
:Member(code, name , std::string(), children)
{}
template<typename Iterable>
inline
Member(TypeCode code, const std::string& name, const Iterable& children)
:Member(code, name , std::string(), children)
{}
PVXS_API
void addChild(const Member& mem);
@@ -250,7 +269,11 @@ CASE(AnyA)
#define CASE(TYPE) \
inline Member TYPE(const std::string& name, std::initializer_list<Member> children) { return Member(TypeCode::TYPE, name, children); } \
inline Member TYPE(const std::string& name, const std::string& id, std::initializer_list<Member> children) { return Member(TypeCode::TYPE, name, id, children); }
template <typename Iterable> \
inline Member TYPE(const std::string& name, const Iterable& children) { return Member(TypeCode::TYPE, name, children); } \
inline Member TYPE(const std::string& name, const std::string& id, std::initializer_list<Member> children) { return Member(TypeCode::TYPE, name, id, children); } \
template <typename Iterable> \
inline Member TYPE(const std::string& name, const std::string& id, const Iterable& children) { return Member(TypeCode::TYPE, name, id, children); }
CASE(Struct)
CASE(Union)
@@ -294,7 +317,16 @@ public:
~TypeDef();
//! new definition with id and children. code must be TypeCode::Struct or TypeCode::Union
TypeDef(TypeCode code, const std::string& id, std::initializer_list<Member> children);
template<typename Iterable>
TypeDef(TypeCode code, const std::string& id, const Iterable& children)
:TypeDef(std::make_shared<Member>(code, "", id, children))
{}
TypeDef(TypeCode code, const std::string& id, std::initializer_list<Member> children)
:TypeDef(std::make_shared<Member>(code, "", id, children))
{}
private:
TypeDef(std::shared_ptr<const Member>&&);
public:
//! new definition for a single scalar field. code must __not__ be TypeCode::Struct or TypeCode::Union
TypeDef(TypeCode code)
:TypeDef(code, std::string(), {})
@@ -304,8 +336,33 @@ public:
:TypeDef(code, std::string(), children)
{}
Member as(const std::string& name) const;
private:
std::shared_ptr<Member> _append_start();
static
void _append(Member& edit, const Member& mem);
void _append_finish(std::shared_ptr<Member>&& edit);
public:
//! append additional children. Only for TypeCode::Struct or TypeCode::Union
TypeDef& operator+=(std::initializer_list<Member> children);
template<typename Iterable>
TypeDef& operator+=(const Iterable& children) {
auto edit = _append_start();
for(auto& child : children) {
_append(edit, child);
}
_append_finish(std::move(edit));
return *this;
}
TypeDef& operator+=(std::initializer_list<Member> children) {
auto edit = _append_start();
for(auto& child : children) {
_append(*edit, child);
}
_append_finish(std::move(edit));
return *this;
}
//! Instanciate this definition
Value create() const;
+31 -28
View File
@@ -22,8 +22,6 @@ struct Member::Helper {
static
void copy_tree(const FieldDesc* desc, Member& node);
static
void append_tree(Member& node, const Member& adopt);
static
void show_Node(std::ostream& strm, const std::string& name, const Member* node, unsigned level=0);
};
@@ -161,14 +159,12 @@ void name_validate(const char *name)
}
}
Member::Member(TypeCode code, const std::string& name, const std::string& id, std::initializer_list<Member> children)
:code(code), name(name), id(id)
void Member::_validate() const
{
if(!name.empty())
name_validate(name.c_str());
for(auto& child : children) {
Helper::node_validate(this, child.id, child.code);
this->children.push_back(child);
}
}
@@ -233,10 +229,8 @@ void Member::Helper::build_tree(std::vector<FieldDesc>& desc, const Member& node
assert(desc.size()==index+desc[index].size());
}
TypeDef::TypeDef(TypeCode code, const std::string& id, std::initializer_list<Member> children)
TypeDef::TypeDef(std::shared_ptr<const Member>&& temp)
{
auto temp(std::make_shared<Member>(code, "", id, children));
auto tempdesc = std::make_shared<std::vector<FieldDesc>>();
Member::Helper::build_tree(*tempdesc, *temp);
@@ -278,7 +272,33 @@ TypeDef::TypeDef(const Value& val)
TypeDef::~TypeDef() {}
void Member::Helper::append_tree(Member& node, const Member& adopt)
Member TypeDef::as(const std::string& name) const
{
if(!top)
throw std::logic_error("Can't append empty TypeDef");
Member ret(*top);
ret.name = name;
return ret;
}
std::shared_ptr<Member> TypeDef::_append_start()
{
if(!top || (top->code!=TypeCode::Struct && top->code!=TypeCode::Union))
throw std::logic_error("May only append to Struct or Union");
std::shared_ptr<Member> edit;
if(top.use_count()==1u) {
edit = std::const_pointer_cast<Member>(top);
top.reset(); // so we don't leave partial tree on error.
} else {
edit = std::make_shared<Member>(*top); // copy
}
return edit;
}
void TypeDef::_append(Member& node, const Member& adopt)
{
for(auto& child : node.children) {
if(child.name==adopt.name) {
@@ -293,7 +313,7 @@ void Member::Helper::append_tree(Member& node, const Member& adopt)
child.id = adopt.id;
for(auto& grandchild : adopt.children) {
append_tree(child, grandchild);
_append(child, grandchild);
}
return;
}
@@ -303,23 +323,8 @@ void Member::Helper::append_tree(Member& node, const Member& adopt)
node.children.push_back(adopt);
}
TypeDef& TypeDef::operator+=(std::initializer_list<Member> children)
void TypeDef::_append_finish(std::shared_ptr<Member>&& edit)
{
if(!top || (top->code!=TypeCode::Struct && top->code!=TypeCode::Union))
throw std::logic_error("May only append to Struct or Union");
std::shared_ptr<Member> edit;
if(top.use_count()==1u) {
edit = std::const_pointer_cast<Member>(top);
top.reset(); // so we don't leave partial tree on error.
} else {
edit = std::make_shared<Member>(*top); // copy
}
for(auto& child : children) {
Member::Helper::append_tree(*edit, child);
}
auto temp = std::make_shared<std::vector<FieldDesc>>();
Member::Helper::build_tree(*temp, *edit);
@@ -327,8 +332,6 @@ TypeDef& TypeDef::operator+=(std::initializer_list<Member> children)
top = std::move(edit);
desc = std::move(type);
return *this;
}
Value TypeDef::create() const