mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-19 00:30:34 +08:00
Refactored unions
This commit is contained in:
@@ -121,6 +121,9 @@ struct UAVCAN_EXPORT ${t.cpp_type_name}
|
||||
private:
|
||||
typename ::uavcan::StorageType< TagType >::Type _tag_; // The name is mangled to avoid clashing with fields
|
||||
|
||||
template <typename Tag::Type T>
|
||||
struct TagToType;
|
||||
|
||||
public:
|
||||
% endif
|
||||
|
||||
@@ -161,61 +164,31 @@ public:
|
||||
|
||||
% if union:
|
||||
/**
|
||||
* Constructors and assignment operators will only work if T is unique within the union; otherwise
|
||||
* compilation will fail with an error referring to ambiguous template instantiation.
|
||||
*/
|
||||
template <typename T>
|
||||
${type_name}(const T& x)
|
||||
% for idx,a in enumerate([x for x in fields if not x.void]):
|
||||
${':' if idx == 0 else ','} ${a.name}()
|
||||
% endfor
|
||||
% if union:
|
||||
, _tag_()
|
||||
% endif
|
||||
{
|
||||
to<T>() = x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
${type_name}& operator=(const T& x)
|
||||
{
|
||||
to<T>() = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use explicit tag access if the union contains non-unique types.
|
||||
* Otherwise it is safer to use as<>(), to<>(), is<>().
|
||||
* Explicit access to the tag.
|
||||
* It is safer to use is()/as()/to() instead.
|
||||
*/
|
||||
typename Tag::Type getTag() const { return typename Tag::Type(_tag_); }
|
||||
void setTag(typename Tag::Type x) { _tag_ = typename ::uavcan::StorageType< TagType >::Type(x); }
|
||||
|
||||
/**
|
||||
* Whether the union is set to the given type.
|
||||
* Access by type; this will only work if the type is unique within the union; otherwise compilation will fail.
|
||||
*/
|
||||
template <typename T>
|
||||
bool is() const;
|
||||
|
||||
/**
|
||||
* Whether the union is set to the given type.
|
||||
* Access by tag; this will work even if there are non-unique types within the union.
|
||||
*/
|
||||
bool is(typename Tag::Type x) const { return Tag::Type(_tag_) == x; }
|
||||
bool is(typename Tag::Type x) const { return typename Tag::Type(_tag_) == x; }
|
||||
|
||||
/**
|
||||
* If the union is currently set to the type T, returns pointer to the appropriate field.
|
||||
* If the union is set to another type, returns null pointer.
|
||||
*/
|
||||
template <typename T>
|
||||
const typename ::uavcan::StorageType<T>::Type* as() const;
|
||||
template <typename Tag::Type T>
|
||||
const typename TagToType<T>::StorageType* as() const;
|
||||
|
||||
/**
|
||||
* Switches the union to the given type and returns a mutable reference to the appropriate field.
|
||||
* If the previous type was different, a default constructor will be executed.
|
||||
* If the previous type was different, a default constructor will be called first.
|
||||
*/
|
||||
template <typename T>
|
||||
typename ::uavcan::StorageType<T>::Type& to();
|
||||
template <typename Tag::Type T>
|
||||
typename TagToType<T>::StorageType& to();
|
||||
% endif
|
||||
<!--(end)-->
|
||||
|
||||
@@ -378,54 +351,32 @@ ${generate_codec_calls_per_field(call_name='encode', self_parameter_type='Parame
|
||||
${generate_codec_calls_per_field(call_name='decode', self_parameter_type='ReferenceType')}
|
||||
|
||||
% if union:
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, bool>::Type ${scope_prefix}<0>::is() const
|
||||
{
|
||||
return is<typename T::StorageType>();
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, const typename T::StorageType*>::Type
|
||||
${scope_prefix}<0>::as() const
|
||||
{
|
||||
return as<typename T::StorageType>();
|
||||
}
|
||||
|
||||
template <>
|
||||
template <typename T>
|
||||
typename ::uavcan::EnableIfType< typename T::StorageType, typename T::StorageType&>::Type
|
||||
${scope_prefix}<0>::to()
|
||||
{
|
||||
return to<typename T::StorageType>();
|
||||
}
|
||||
|
||||
% for idx,a in enumerate(fields):
|
||||
template <>
|
||||
template <>
|
||||
bool ${scope_prefix}<0>::is< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >() const
|
||||
struct ${scope_prefix}<0>::TagToType<${scope_prefix}<0>::Tag::${a.name}>
|
||||
{
|
||||
return _tag_ == ${idx};
|
||||
typedef typename ${scope_prefix}<0>::FieldTypes::${a.name} Type;
|
||||
typedef typename ::uavcan::StorageType<Type>::Type StorageType;
|
||||
};
|
||||
|
||||
template <>
|
||||
template <>
|
||||
const typename ${scope_prefix}<0>::TagToType< ${scope_prefix}<0>::Tag::${a.name} >::StorageType*
|
||||
${scope_prefix}<0>::as< ${scope_prefix}<0>::Tag::${a.name} >() const
|
||||
{
|
||||
return is(${scope_prefix}<0>::Tag::${a.name}) ? &${a.name} : NULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
const typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type*
|
||||
${scope_prefix}<0>::as< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >() const
|
||||
{
|
||||
return is< typename ${scope_prefix}<0>::FieldTypes::${a.name} >() ? &${a.name} : NULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type&
|
||||
${scope_prefix}<0>::to< typename ::uavcan::StorageType< typename ${scope_prefix}<0>::FieldTypes::${a.name} >::Type >()
|
||||
typename ${scope_prefix}<0>::TagToType< ${scope_prefix}<0>::Tag::${a.name} >::StorageType&
|
||||
${scope_prefix}<0>::to< ${scope_prefix}<0>::Tag::${a.name} >()
|
||||
{
|
||||
if (_tag_ != ${idx})
|
||||
{
|
||||
_tag_ = ${idx};
|
||||
${a.name} = typename ::uavcan::StorageType< typename FieldTypes::${a.name} >::Type();
|
||||
${a.name} = typename TagToType< ${scope_prefix}<0>::Tag::${a.name} >::StorageType();
|
||||
}
|
||||
return ${a.name};
|
||||
}
|
||||
|
||||
@@ -110,14 +110,14 @@ class UAVCAN_EXPORT ParamServer
|
||||
}
|
||||
|
||||
// Assign if needed, read back
|
||||
if (!in.value.is<protocol::param::Empty>())
|
||||
if (!in.value.is(protocol::param::Value::Tag::empty))
|
||||
{
|
||||
manager_->assignParamValue(out.name, in.value);
|
||||
}
|
||||
manager_->readParamValue(out.name, out.value);
|
||||
|
||||
// Check if the value is OK, otherwise reset the name to indicate that we have no idea what is it all about
|
||||
if (!out.value.is<protocol::param::Empty>())
|
||||
if (!out.value.is(protocol::param::Value::Tag::empty))
|
||||
{
|
||||
manager_->readParamDefaultMaxMin(out.name, out.default_value, out.max_value, out.min_value);
|
||||
}
|
||||
|
||||
@@ -32,22 +32,22 @@ struct ParamServerTestManager : public uavcan::IParamManager
|
||||
KeyValue::iterator it = kv.find(name.c_str());
|
||||
if (it != kv.end())
|
||||
{
|
||||
if (value.is<bool>())
|
||||
if (value.is(Value::Tag::boolean_value))
|
||||
{
|
||||
assert(value.getTag() == Value::Tag::boolean_value);
|
||||
it->second = double(value.boolean_value);
|
||||
}
|
||||
else if (value.is<Value::FieldTypes::integer_value>())
|
||||
else if (value.is(Value::Tag::integer_value))
|
||||
{
|
||||
assert(value.getTag() == Value::Tag::integer_value);
|
||||
it->second = double(value.integer_value);
|
||||
}
|
||||
else if (value.is<float>())
|
||||
else if (value.is(Value::Tag::real_value))
|
||||
{
|
||||
assert(value.getTag() == Value::Tag::real_value);
|
||||
it->second = double(value.real_value);
|
||||
}
|
||||
else if (value.is<Value::FieldTypes::string_value>())
|
||||
else if (value.is(Value::Tag::string_value))
|
||||
{
|
||||
assert(value.getTag() == Value::Tag::string_value);
|
||||
it->second = std::atof(value.string_value.c_str());
|
||||
@@ -65,7 +65,7 @@ struct ParamServerTestManager : public uavcan::IParamManager
|
||||
KeyValue::const_iterator it = kv.find(name.c_str());
|
||||
if (it != kv.end())
|
||||
{
|
||||
out_value = float(it->second);
|
||||
out_value.to<Value::Tag::real_value>() = float(it->second);
|
||||
assert(out_value.getTag() == Value::Tag::real_value);
|
||||
}
|
||||
std::cout << "READ [" << name.c_str() << "]\n" << out_value << "\n---" << std::endl;
|
||||
@@ -141,10 +141,10 @@ TEST(ParamServer, Basic)
|
||||
// No such variable, shall return empty name/value
|
||||
get_set_rq.index = 0;
|
||||
get_set_rq.name.clear();
|
||||
get_set_rq.value = uavcan::int64_t(0xDEADBEEF);
|
||||
get_set_rq.value.to<uavcan::protocol::param::Value::Tag::integer_value>() = 0xDEADBEEF;
|
||||
doCall(get_set_cln, get_set_rq, nodes);
|
||||
ASSERT_TRUE(get_set_cln.collector.result->getResponse().name.empty());
|
||||
ASSERT_TRUE(get_set_cln.collector.result->getResponse().value.is<uavcan::protocol::param::Empty>());
|
||||
ASSERT_TRUE(get_set_cln.collector.result->getResponse().value.is(uavcan::protocol::param::Value::Tag::empty));
|
||||
|
||||
mgr.kv["foobar"] = 123.456; // New param
|
||||
|
||||
@@ -153,21 +153,24 @@ TEST(ParamServer, Basic)
|
||||
get_set_rq.name = "foobar";
|
||||
doCall(get_set_cln, get_set_rq, nodes);
|
||||
ASSERT_STREQ("foobar", get_set_cln.collector.result->getResponse().name.c_str());
|
||||
ASSERT_TRUE(get_set_cln.collector.result->getResponse().value.is<float>());
|
||||
ASSERT_FLOAT_EQ(123.456F, get_set_cln.collector.result->getResponse().value.to<float>());
|
||||
ASSERT_TRUE(get_set_cln.collector.result->getResponse().value.is(uavcan::protocol::param::Value::Tag::real_value));
|
||||
ASSERT_FLOAT_EQ(123.456F, get_set_cln.collector.result->getResponse().value.
|
||||
to<uavcan::protocol::param::Value::Tag::real_value>());
|
||||
|
||||
// Set by index
|
||||
get_set_rq = uavcan::protocol::param::GetSet::Request();
|
||||
get_set_rq.index = 0;
|
||||
get_set_rq.value = uavcan::protocol::param::Value::FieldTypes::string_value("424242");
|
||||
get_set_rq.value.to<uavcan::protocol::param::Value::Tag::string_value>() = "424242";
|
||||
doCall(get_set_cln, get_set_rq, nodes);
|
||||
ASSERT_STREQ("foobar", get_set_cln.collector.result->getResponse().name.c_str());
|
||||
ASSERT_FLOAT_EQ(424242, get_set_cln.collector.result->getResponse().value.to<float>());
|
||||
ASSERT_FLOAT_EQ(424242, get_set_cln.collector.result->getResponse().value.
|
||||
to<uavcan::protocol::param::Value::Tag::real_value>());
|
||||
|
||||
// Get by index
|
||||
get_set_rq = uavcan::protocol::param::GetSet::Request();
|
||||
get_set_rq.index = 0;
|
||||
doCall(get_set_cln, get_set_rq, nodes);
|
||||
ASSERT_STREQ("foobar", get_set_cln.collector.result->getResponse().name.c_str());
|
||||
ASSERT_FLOAT_EQ(424242, get_set_cln.collector.result->getResponse().value.to<float>());
|
||||
ASSERT_FLOAT_EQ(424242, get_set_cln.collector.result->getResponse().value.
|
||||
to<uavcan::protocol::param::Value::Tag::real_value>());
|
||||
}
|
||||
|
||||
@@ -76,19 +76,19 @@ public:
|
||||
|
||||
std::string paramValueToString(const uavcan::protocol::param::Value& value)
|
||||
{
|
||||
if (auto x = value.as<bool>())
|
||||
if (auto x = value.as<uavcan::protocol::param::Value::Tag::boolean_value>())
|
||||
{
|
||||
return *x ? "true" : "false";
|
||||
}
|
||||
if (auto x = value.as<std::int64_t>())
|
||||
if (auto x = value.as<uavcan::protocol::param::Value::Tag::integer_value>())
|
||||
{
|
||||
return std::to_string(*x);
|
||||
}
|
||||
if (auto x = value.as<float>())
|
||||
if (auto x = value.as<uavcan::protocol::param::Value::Tag::real_value>())
|
||||
{
|
||||
return std::to_string(*x);
|
||||
}
|
||||
if (auto x = value.as<uavcan::protocol::param::Value::FieldTypes::string_value>())
|
||||
if (auto x = value.as<uavcan::protocol::param::Value::Tag::string_value>())
|
||||
{
|
||||
return std::string(x->c_str()) + " ";
|
||||
}
|
||||
@@ -97,11 +97,11 @@ std::string paramValueToString(const uavcan::protocol::param::Value& value)
|
||||
|
||||
std::string paramValueToString(const uavcan::protocol::param::NumericValue& value)
|
||||
{
|
||||
if (auto x = value.as<std::int64_t>())
|
||||
if (auto x = value.as<uavcan::protocol::param::NumericValue::Tag::integer_value>())
|
||||
{
|
||||
return std::to_string(*x);
|
||||
}
|
||||
if (auto x = value.as<float>())
|
||||
if (auto x = value.as<uavcan::protocol::param::NumericValue::Tag::real_value>())
|
||||
{
|
||||
return std::to_string(*x);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ const std::map<std::string,
|
||||
{
|
||||
request.name = args.at(0).c_str();
|
||||
// TODO: add support for string parameters
|
||||
request.value = std::stof(args.at(1));
|
||||
request.value.to<uavcan::protocol::param::Value::Tag::real_value>() = std::stof(args.at(1));
|
||||
printGetSetResponse(call(*client, node_id, request));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user