Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default values for stuct members and scalar initialization of array members #795

Merged
merged 40 commits into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
64265b2
Added support for default attributes in discrete enum declaration in XML
rohandkn Jun 1, 2021
3e9de5f
Added tests and fixed header file include in hpp file
rohandkn Jun 2, 2021
7fa2bbb
Added enum fixes to cpp template, changed default documentation, and …
rohandkn Jun 3, 2021
3b16b49
Added enum fixes to cpp template, changed default documentation, and …
rohandkn Jun 3, 2021
a38da2d
Added test for uninitialized value for not-set default values
rohandkn Jun 3, 2021
7893fe8
Added nothing
rohandkn Jun 3, 2021
fa5c69c
Removed changes from gitignore
rohandkn Jun 3, 2021
80117c2
Added default value tests for enum
rohandkn Jun 3, 2021
cb93785
Added minor changes to improve readability of enum default value init…
rohandkn Jun 7, 2021
38e64b3
Added support for default values for members in serializable structs
rohandkn Jun 7, 2021
b0e20e9
Added support for default values for members in serializable structs
rohandkn Jun 7, 2021
2513167
Removed unneeded files
rohandkn Jun 7, 2021
b6d5608
Added preliminary changes to adding default to struct members
rohandkn Jun 8, 2021
beec355
Added test for default initializaion of serializable structs
rohandkn Jun 8, 2021
292a2df
Resolved merge conflict
rohandkn Jun 8, 2021
763360c
Resolved merge conflict
rohandkn Jun 8, 2021
657bb61
Merge pull request #4 from nasa/devel
rohandkn Jun 8, 2021
e40bc9d
Removed minor unneeded lines/formatting errors
rohandkn Jun 8, 2021
f38bda5
Changed default structure to element instead of attribute
rohandkn Jun 9, 2021
bfde770
Removed unneeded lines
rohandkn Jun 9, 2021
807a477
Fixed test for serializable member default
rohandkn Jun 10, 2021
cfbb9ef
Added newline for consistency
rohandkn Jun 10, 2021
7b14a77
Made changes to allow interleave in schema
rohandkn Jun 17, 2021
947ebae
Minor change to xml-specification
rohandkn Jun 17, 2021
b4009b7
Added seperate test for serializable structs - first test is default …
rohandkn Jun 17, 2021
8f5da2a
Minor change to xml-specification
rohandkn Jun 17, 2021
0a9fa58
Added functions to support scalar array initialization
rohandkn Jun 21, 2021
34702db
Added comments and made stylistic changes
rohandkn Jun 21, 2021
bc94d06
Removed newline at eof
rohandkn Jun 21, 2021
a59be98
Completed array scalar constructor test
rohandkn Jun 21, 2021
d2c092d
Added minor comment changes
rohandkn Jun 21, 2021
11fe226
Made minor specification changes
rohandkn Jun 22, 2021
ff1002a
Added scalar default values for array members and correspondng structs
rohandkn Jun 22, 2021
5167dc2
Fixed test for member arrays with scalar initialization
rohandkn Jun 22, 2021
9d6164d
Merge branch 'scalar-default-member' into serial-default
rohandkn Jun 28, 2021
b082264
Merge pull request #11 from rohandkn/serial-default
rohandkn Jun 28, 2021
419c743
Fixes for merge conflicts and dependecycies
rohandkn Jun 28, 2021
2d83434
Made minor formatting changes and fixed build issue
rohandkn Jun 29, 2021
7da27e2
Minor formatting change
rohandkn Jun 29, 2021
2df0565
Reverted delete from xml specification document'
rohandkn Jun 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Autocoders/Python/schema/default/serializable_schema.rng
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,19 @@
</attribute>
</optional>

<!-- Type, size, and internal enum define are defined within this ref -->
<ref name="type_size_choice_define"/>
<!-- Optional element -->

<interleave>
<optional>
<a:documentation>Optional default value.</a:documentation>
<element name="default">
<text/>
</element>
</optional>

<!-- Type, size, and internal enum define are defined within this ref -->
<ref name="type_size_choice_define"/>
</interleave>
</element>
</define>
</grammar>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace ${n} {
#end for
#end if
#for ($memname,$type,$size,$format,$comment) in $mem_list:
#for ($memname,$type,$size,$format,$comment,$default) in $mem_list:
#if $type == "string":

${name}::${memname}String::${memname}String(const char* src): StringBase() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace ${n} {

class ${name} : public Fw::Serializable {

#for ($memname,$type,$size,$format,$comment) in $mem_list:
#for ($memname,$type,$size,$format,$comment,$default) in $mem_list:
#if $type == "string":

public:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
// public methods

${name}::${name}(void): Serializable() {

#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $default != None and $size != None and $typeinfo != "string":
for (NATIVE_INT_TYPE _mem = 0; _mem < ${size}; _mem++) {
this->m_${member}[_mem] = ${default};
}
#else if $default != None:
this->m_${member} = ${default};
#end if
#end for
}

${name}::${name}(const ${name}& src) : Serializable() {
Expand All @@ -17,21 +25,36 @@ ${name}::${name}(${args_proto_string}) : Serializable() {
this->set(${args_string});
}

#if $args_scalar_array_string:
${name}::${name}(${args_scalar_array_string}) : Serializable() {
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
this->m_${member} = ${member};
#else
for (NATIVE_INT_TYPE _mem = 0; _mem < ${size}; _mem++) {
this->m_${member}[_mem] = ${member};
}
#end if
#end for
}

#end if

const ${name}& ${name}::operator=(const ${name}& src) {
this->set(${args_mstring});
return src;
}

bool ${name}::operator==(const ${name}& src) const {
return (
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
(src.m_$member == this->m_$member) &&
#end for
true);
}

void ${name}::set(${args_proto_string}) {
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
this->m_${member} = ${member};
#else
Expand All @@ -42,7 +65,7 @@ void ${name}::set(${args_proto_string}) {
#end for
}

#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None:
${type} ${name}::get${member}(void) {
return this->m_${member};
Expand All @@ -57,7 +80,7 @@ const ${type}* ${name}::get${member}(NATIVE_INT_TYPE& size) {
}

#end for
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None:
void ${name}::set${member}(${type} val) {
this->m_${member} = val;
Expand All @@ -82,7 +105,7 @@ Fw::SerializeStatus ${name}::serialize(Fw::SerializeBufferBase& buffer) const {
stat = buffer.serialize((U32)${name}::TYPE_ID);
\#endif

#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
#if $typeinfo == "enum":
stat = buffer.serialize((FwEnumStoreType)this->m_${member});
Expand Down Expand Up @@ -120,7 +143,7 @@ Fw::SerializeStatus ${name}::deserialize(Fw::SerializeBufferBase& buffer) {
}
\#endif

#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size == None or $typeinfo == "string":
#if $typeinfo == "enum"
FwEnumStoreType int${member} = 0;
Expand Down Expand Up @@ -150,7 +173,7 @@ void ${name}::toString(Fw::StringBase& text) const {

static const char * formatString =
"("
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members[0:-1]:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members[0:-1]:
#if $size != None and typeinfo != "string":
"$member = "
#for $elem in range(0,int($size)-1):
Expand All @@ -174,7 +197,7 @@ void ${name}::toString(Fw::StringBase& text) const {

// declare strings to hold any serializable toString() arguments

#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $typeinfo == "extern":

Fw::EightyCharString ${member}Str;
Expand All @@ -184,7 +207,7 @@ void ${name}::toString(Fw::StringBase& text) const {

char outputString[FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE];
(void)snprintf(outputString,FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE,formatString
#for ($member,$type,$size,$format,$comment,$typeinfo) in $members:
#for ($member,$type,$size,$format,$comment,$default,$typeinfo) in $members:
#if $size != None and $typeinfo != "string":
#for $elem in range(0,int($size)):
#if $type == "bool":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public:
${name}(const ${name}* src); //!< pointer copy constructor
${name}(const ${name}& src); //!< reference copy constructor
${name}($args_proto); //!< constructor with arguments
#if $args_proto_scalar_init:
${name}($args_proto_scalar_init); //!< constructor with arguments with scalars for array arguments
#end if
const ${name}& operator=(const ${name}& src); //!< equal operator
bool operator==(const ${name}& src) const; //!< equality operator
#ifdef BUILD_UT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def _get_args_proto_string(self, obj):
for use in templates that generate prototypes.
"""
arg_str = ""
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
Expand Down Expand Up @@ -128,7 +128,7 @@ def _get_conv_mem_list(self, obj):
"""
arg_list = list()

for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
typeinfo = None
if isinstance(mtype, tuple):
mtype = mtype[0][1]
Expand All @@ -139,10 +139,36 @@ def _get_conv_mem_list(self, obj):
elif mtype not in typelist:
typeinfo = "extern"

arg_list.append((name, mtype, size, format, comment, typeinfo))

arg_list.append((name, mtype, size, format, comment, default, typeinfo))
return arg_list

def _get_args_proto_string_scalar_init(self, obj):
"""
Return a string of (type, name) args, comma separated
for use in templates that generate prototypes where the array
arguments are represented by single element values. If no arguments
are arrays, function returns None.
"""
arg_str = ""
contains_array = False
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
arg_str += "const {}::{}String& {}, ".format(obj.get_name(), name, name)
elif mtype not in typelist:
arg_str += "const {}& {}, ".format(mtype, name)
elif size is not None:
arg_str += "const {} {}, ".format(mtype, name)
contains_array = True
else:
arg_str += "{} {}".format(mtype, name)
arg_str += ", "
if not contains_array:
return None
arg_str = arg_str.strip(", ")
return arg_str

def _writeTmpl(self, c, visit_str):
"""
Wrapper to write tmpl to files desc.
Expand Down Expand Up @@ -267,6 +293,7 @@ def publicVisit(self, obj):
c.args_string = self._get_args_string(obj)
c.args_mstring = self._get_args_string(obj, "src.m_")
c.args_mstring_ptr = self._get_args_string(obj, "src->m_")
c.args_scalar_array_string = self._get_args_proto_string_scalar_init(obj)
c.members = self._get_conv_mem_list(obj)
self._writeTmpl(c, "publicVisit")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _get_args_string(self, obj):
for use in templates that generate prototypes.
"""
arg_str = ""
for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
Expand All @@ -105,13 +105,40 @@ def _get_args_string(self, obj):
arg_str = arg_str.strip(", ")
return arg_str

def _get_args_string_scalar_init(self, obj):
"""
Return a string of (type, name) args, comma separated
where array arguments are represented by single element
values for use in templates that generate prototypes.
If no arguments are arrays, function returns None.
"""
arg_str = ""
contains_array = False
for (name, mtype, size, format, comment, default) in obj.get_members():
if isinstance(mtype, tuple):
arg_str += "{} {}, ".format(mtype[0][1], name)
elif mtype == "string":
arg_str += "const {}::{}String& {}, ".format(obj.get_name(), name, name)
elif mtype not in typelist:
arg_str += "const {}& {}, ".format(mtype, name)
elif size is not None:
arg_str += "const {} {}, ".format(mtype, name)
contains_array = True
else:
arg_str += "{} {}".format(mtype, name)
arg_str += ", "
if not contains_array:
return None
arg_str = arg_str.strip(", ")
return arg_str

def _get_conv_mem_list(self, obj):
"""
Return a list of port argument tuples
"""
arg_list = list()

for (name, mtype, size, format, comment) in obj.get_members():
for (name, mtype, size, format, comment, default) in obj.get_members():
typeinfo = None
if isinstance(mtype, tuple):
mtype = mtype[0][1]
Expand Down Expand Up @@ -282,6 +309,7 @@ def publicVisit(self, obj):
c = publicSerialH.publicSerialH()
c.name = obj.get_name()
c.args_proto = self._get_args_string(obj)
c.args_proto_scalar_init = self._get_args_string_scalar_init(obj)
c.members = self._get_conv_mem_list(obj)
self._writeTmpl(c, "publicVisit")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ def __init__(self, xml_file=None):
else:
c = None

d = None

for member_tag in member:
if member_tag.tag == "enum" and t == "ENUM":
en = member_tag.attrib["name"]
Expand All @@ -222,14 +224,16 @@ def __init__(self, xml_file=None):
mc = None
enum_members.append((mn, v, mc))
t = ((t, en), enum_members)
elif member_tag.tag == "default":
d = member_tag.text
else:
PRINT.info(
"%s: Invalid member tag %s in serializable member %s"
% (xml_file, member_tag.tag, n)
)
sys.exit(-1)

self.__members.append((n, t, s, f, c))
self.__members.append((n, t, s, f, c, d))

#
# Generate a type id here using SHA256 algorithm and XML stringified file.
Expand Down
3 changes: 3 additions & 0 deletions Autocoders/Python/src/fprime_ac/utils/TopDictGenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def check_for_serial_xml(self):
member_size,
member_format_specifier,
member_comment,
member_default,
) in serializable_model.get_members():
member_elem = etree.Element("member")
member_elem.attrib["name"] = member_name
Expand All @@ -79,6 +80,8 @@ def check_for_serial_xml(self):
] = member_format_specifier
if member_comment is not None:
member_elem.attrib["description"] = member_comment
if member_default is not None:
member_elem.attrib["default"] = member_default
if isinstance(member_type, tuple):
type_name = "{}::{}::{}".format(
serializable_type,
Expand Down
1 change: 1 addition & 0 deletions Autocoders/Python/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize_user")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize1")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize2")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize3")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/serialize4")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/stress")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/string_port")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/telem_tester")
Expand Down
3 changes: 1 addition & 2 deletions Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
<members>
<member name="Member1" type="U32" comment = "Example member 1"/>
<member name="Member2" type="U32" comment = "Example member 2"/>
<member name="Member3" type="Example::Enum1" comment = "Example enum member">
</member>
<member name="Member3" type="Example::Enum1" comment = "Example enum member"/>
</members>
</serializable>

22 changes: 22 additions & 0 deletions Autocoders/Python/test/serialize4/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ======================================================================
# CMakeLists.txt
# ======================================================================

# We need to declare the XML source files this way to invoke the autocoder.
# However, only the UT build is allowed here.
set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/Serial1SerializableAi.xml"
)
register_fprime_module()

# Declare dependencies on test modules
set(UT_MOD_DEPS
Fw/Test
STest
)

# List all .cpp files as UT_SOURCE_FILES. Only the UT build is allowed.
set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/main.cpp"
)
register_fprime_ut()
10 changes: 10 additions & 0 deletions Autocoders/Python/test/serialize4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Autocoders/Python/test/serialize4

This directory contains unit tests for the Python serialize XML code generator.

To use this directory, you must have installed F Prime, and you must be inside
the F Prime Python virtual environment.

* To build the tests, run `./build`
* To run the tests, run `./run`
* To run coverage analysis, run `./cov`
Loading