Skip to content

Commit

Permalink
Adds support for Offset(n) attribute in the CDI (#765)
Browse files Browse the repository at this point in the history
Adds support for Offset(n) attribute in the CDI for individual entries, including groups, atoms (like string) or number entries.

It is also supported to declare a negative offset, which is a typical use- case when the entries are displayed out of order, or when one source data needs to be displayed in two ways.

Previous Offset() was only supported on segments, which are a form of groups. With this PR, the declaration is moved up to the root class of all config entries. From then on every entry must have some form of definition.
Also adjusts how the c++ constexpr generates the offset() attribute to take this into account.
  • Loading branch information
balazsracz authored Jan 28, 2024
1 parent 5c1f88a commit b53552b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
36 changes: 31 additions & 5 deletions src/openlcb/ConfigRenderer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include <climits>
#include <string>
#include <stdint.h>

#include "openlcb/SimpleNodeInfoDefs.hxx"
#include "utils/OptionalArgs.hxx"
Expand All @@ -52,7 +53,8 @@ struct AtomConfigDefs
DECLARE_OPTIONALARG(Description, description, const char *, 1, nullptr);
DECLARE_OPTIONALARG(MapValues, mapvalues, const char *, 2, nullptr);
DECLARE_OPTIONALARG(SkipInit, skip_init, int, 15, 0);
using Base = OptionalArg<AtomConfigDefs, Name, Description, MapValues, SkipInit>;
DECLARE_OPTIONALARG(Offset, offset, int, 10, 0);
using Base = OptionalArg<AtomConfigDefs, Name, Description, MapValues, SkipInit, Offset>;
};

/// Configuration implementation class for CDI Atom elements (strings, events
Expand All @@ -72,6 +74,10 @@ public:
/// When set to true, the event initializers will be skipped in this event
/// or group.
DEFINE_OPTIONALARG(SkipInit, skip_init, int);
/// Represents the 'offset' attribute for groups and elements and the
/// 'origin' attribute for segments.
DEFINE_OPTIONALARG(Offset, offset, int);


void render_cdi(std::string *r) const
{
Expand Down Expand Up @@ -115,6 +121,11 @@ public:
{
*s += StringPrintf(" size=\'%u\'", size_);
}
int ofs = AtomConfigOptions(args...).offset();
if (ofs != 0)
{
*s += StringPrintf(" offset=\'%d\'", ofs);
}
*s += ">\n";
AtomConfigOptions(args...).render_cdi(s);
*s += StringPrintf("</%s>\n", tag_);
Expand All @@ -136,7 +147,7 @@ struct NumericConfigDefs : public AtomConfigDefs
DECLARE_OPTIONALARG(Max, maxvalue, int, 7, INT_MAX);
DECLARE_OPTIONALARG(Default, defaultvalue, int, 8, INT_MAX);
using Base = OptionalArg<NumericConfigDefs, Name, Description, MapValues,
Min, Max, Default, SkipInit>;
Min, Max, Default, SkipInit, Offset>;
};

/// Definitions for the options for numeric CDI entries.
Expand All @@ -157,6 +168,7 @@ public:
DEFINE_OPTIONALARG(Max, maxvalue, int);
DEFINE_OPTIONALARG(Default, defaultvalue, int);
DEFINE_OPTIONALARG(SkipInit, skip_init, int);
DEFINE_OPTIONALARG(Offset, offset, int);

void render_cdi(std::string *r) const
{
Expand Down Expand Up @@ -222,6 +234,11 @@ public:
{
*s += StringPrintf(" size=\'%u\'", size_);
}
int ofs = NumericConfigOptions(args...).offset();
if (ofs != 0)
{
*s += StringPrintf(" offset=\'%d\'", ofs);
}
*s += ">\n";
NumericConfigOptions(args...).render_cdi(s);
*s += StringPrintf("</%s>\n", tag_);
Expand All @@ -241,13 +258,12 @@ struct GroupConfigDefs : public AtomConfigDefs
{
// This is needed for inheriting declarations.
using AtomConfigDefs::check_arguments_are_valid;
DECLARE_OPTIONALARG(Offset, offset, int, 10, INT_MAX);
DECLARE_OPTIONALARG(Segment, segment, int, 11, -1);
DECLARE_OPTIONALARG(RepName, repname, const char*, 12, nullptr);
DECLARE_OPTIONALARG(FixedSize, fixed_size, unsigned, 13, 0);
DECLARE_OPTIONALARG(Hidden, hidden, int, 14, 0);
using Base = OptionalArg<GroupConfigDefs, Name, Description, Segment,
Offset, RepName, FixedSize, Hidden>;
Offset, RepName, FixedSize, Hidden>;
};

/// Implementation class for the condifuration options of a CDI group element.
Expand Down Expand Up @@ -415,6 +431,11 @@ public:
{
*s += StringPrintf(" replication='%u'", replication_);
}
int ofs = opts.offset();
if (ofs != 0)
{
*s += StringPrintf(" offset=\'%d\'", ofs);
}
}
else
{
Expand Down Expand Up @@ -456,7 +477,7 @@ struct IdentificationConfigDefs
DECLARE_OPTIONALARG(HwVersion, hardware_version, const char *, 2, nullptr);
DECLARE_OPTIONALARG(SwVersion, software_version, const char *, 3, nullptr);
using Base = OptionalArg<IdentificationConfigDefs, Manufacturer, Model,
HwVersion, SwVersion>;
HwVersion, SwVersion>;
};

/// Configuration implementation options for rendering CDI (identification)
Expand All @@ -476,6 +497,11 @@ public:
{
return 0;
}

constexpr int offset() const
{
return 0;
}
};

/// Helper class for rendering the "<identification>" tag.
Expand Down
3 changes: 2 additions & 1 deletion src/openlcb/ConfigRepresentation.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ public:
"May only have segments inside CDI."); \
return TYPE(group_opts().is_cdi() \
? TYPE(0).group_opts(__VA_ARGS__).get_segment_offset() \
: entry(openlcb::EntryMarker<LINE - 1>()).end_offset()); \
: entry(openlcb::EntryMarker<LINE - 1>()).end_offset() + \
NAME##_options().offset()); \
} \
constexpr TYPE NAME() const \
{ \
Expand Down

0 comments on commit b53552b

Please sign in to comment.