diff --git a/Autocoders/Python/schema/default/serializable_schema.rng b/Autocoders/Python/schema/default/serializable_schema.rng index 7c8d94d674..0f952b733f 100644 --- a/Autocoders/Python/schema/default/serializable_schema.rng +++ b/Autocoders/Python/schema/default/serializable_schema.rng @@ -114,8 +114,19 @@ - - + + + + + Optional default value. + + + + + + + + diff --git a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialCpp.tmpl b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialCpp.tmpl index f0bc5899b5..8aea3e0734 100644 --- a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialCpp.tmpl +++ b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialCpp.tmpl @@ -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() { diff --git a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialH.tmpl b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialH.tmpl index 9560e73770..b857d8b685 100644 --- a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialH.tmpl +++ b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/namespaceSerialH.tmpl @@ -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: diff --git a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/publicSerialCpp.tmpl b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/publicSerialCpp.tmpl index 67c8d09348..c664fdd811 100644 --- a/Autocoders/Python/src/fprime_ac/generators/templates/serialize/publicSerialCpp.tmpl +++ b/Autocoders/Python/src/fprime_ac/generators/templates/serialize/publicSerialCpp.tmpl @@ -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() { @@ -39,14 +47,14 @@ const ${name}& ${name}::operator=(const ${name}& 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 @@ -57,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}; @@ -72,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; @@ -97,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}); @@ -135,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; @@ -165,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): @@ -189,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; @@ -199,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": diff --git a/Autocoders/Python/src/fprime_ac/generators/visitors/SerialCppVisitor.py b/Autocoders/Python/src/fprime_ac/generators/visitors/SerialCppVisitor.py index c700affbea..9b72fbbd68 100644 --- a/Autocoders/Python/src/fprime_ac/generators/visitors/SerialCppVisitor.py +++ b/Autocoders/Python/src/fprime_ac/generators/visitors/SerialCppVisitor.py @@ -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": @@ -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] @@ -139,7 +139,7 @@ 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 diff --git a/Autocoders/Python/src/fprime_ac/generators/visitors/SerialHVisitor.py b/Autocoders/Python/src/fprime_ac/generators/visitors/SerialHVisitor.py index 302a5cbdf2..7277cf06bd 100644 --- a/Autocoders/Python/src/fprime_ac/generators/visitors/SerialHVisitor.py +++ b/Autocoders/Python/src/fprime_ac/generators/visitors/SerialHVisitor.py @@ -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": @@ -138,7 +138,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] diff --git a/Autocoders/Python/src/fprime_ac/parsers/XmlSerializeParser.py b/Autocoders/Python/src/fprime_ac/parsers/XmlSerializeParser.py index a58b38a401..295ff0ac84 100644 --- a/Autocoders/Python/src/fprime_ac/parsers/XmlSerializeParser.py +++ b/Autocoders/Python/src/fprime_ac/parsers/XmlSerializeParser.py @@ -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"] @@ -222,6 +224,8 @@ 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" @@ -229,7 +233,7 @@ def __init__(self, xml_file=None): ) 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. diff --git a/Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml b/Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml index 6c8919bfa6..f562b9e467 100644 --- a/Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml +++ b/Autocoders/Python/test/enum_xml/Serial1SerializableAi.xml @@ -7,8 +7,7 @@ - - + diff --git a/Autocoders/Python/test/serialize4/Serial1SerializableAi.xml b/Autocoders/Python/test/serialize4/Serial1SerializableAi.xml index d90aa2fcbb..2ce1b28d52 100644 --- a/Autocoders/Python/test/serialize4/Serial1SerializableAi.xml +++ b/Autocoders/Python/test/serialize4/Serial1SerializableAi.xml @@ -4,16 +4,23 @@ Some Example Members - - + + 12345 + + + "hello" + + MEM2 + + + 3 - diff --git a/Autocoders/Python/test/serialize4/main.cpp b/Autocoders/Python/test/serialize4/main.cpp index b243f5e8b9..76e62422f4 100644 --- a/Autocoders/Python/test/serialize4/main.cpp +++ b/Autocoders/Python/test/serialize4/main.cpp @@ -4,6 +4,24 @@ using namespace std; +TEST(DefaultValues, OK) { + + Example::Serial1 serial1; + Example::Serial1 serial2; + + // Check serializable default values are correctly set + ASSERT_EQ(serial1.getMember1(), 12345); + ASSERT_EQ(serial1.getMember2(), "hello"); + ASSERT_EQ(serial1.getMember3(), Example::MEM2); + + // Check serializable scalar default for array member is correctly set + NATIVE_INT_TYPE size; + const U32* serial1Member4 = serial1.getMember4(size); + for (NATIVE_INT_TYPE _mem = 0; _mem < size; _mem++) { + ASSERT_EQ(serial1Member4[_mem], 2); + } +} + TEST(Serialize4, ArrayScalarInit) { Example::Serial1 serial1 (0,"hello world",Example::SomeEnum::MEM2,2); diff --git a/docs/UsersGuide/dev/xml-specification.md b/docs/UsersGuide/dev/xml-specification.md index afb91596d9..1e675b6b04 100644 --- a/docs/UsersGuide/dev/xml-specification.md +++ b/docs/UsersGuide/dev/xml-specification.md @@ -62,6 +62,7 @@ specification. | member | name | Defines the member name. | | member | size | Specifies that the member is an array of the type with the specified size. | | member | format | Specifies a format specifier when displaying the member. | +| default | | Specifies the default value of the member (optional). | | enum | | Specifies an enumeration when the member type=ENUM. | | enum | name | Enumeration type name. | | item | | Specifies a member of the enumeration. | @@ -95,11 +96,12 @@ this specification: ```xml - - - - + + + + + OFF @@ -108,7 +110,8 @@ this specification: This file defines a Serializable type `Switch` with one member `state`. Its type is `SwitchState`, which is an enumeration with -enumerated constants `OFF` and `ON`. +enumerated constants `OFF` and `ON`. Using the default child element, +the default value will be OFF. Alternatively, you can specify an enumeration *E* as a separate XML type. Then you can do the following: @@ -609,7 +612,7 @@ specification. | port | max\_number | Specifies the number of ports of this type. This allows multiple callers to the same type of port if knowing the source is necessary. Can be specified as an Fw/Cfg/AcConstants.ini file $VARIABLE value. | | | port | full | Specifies the behavior for async ports when the message queue is full. One of *drop*, *block*, or *assert*, where *assert* is the default. | | | port | role | Specifies the role of the port when the modeler=true. | | -| commands | | Optional. Starts the section where software commands are defined. | | +| commands | | Starts the section where software commands are defined. | | | commands | opcode\_base | Defines the base value for the opcodes in the commands. If this is specified, all opcodes will be added to this value. If it is missing, opcodes will be absolute. This tag can also have a variable of the form $VARIABLE referring to values in Fw/Cfg/AcConstants.ini. | | | command | | Starts the definition for a particular command. | | | command | mnemonic | Defines a text label for the command. Can be alphanumeric with “\_” separators, but no spaces. | |