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

toString doesn't display the last item in a struct #2748

Open
ReggieMarr opened this issue May 25, 2024 · 0 comments
Open

toString doesn't display the last item in a struct #2748

ReggieMarr opened this issue May 25, 2024 · 0 comments
Labels

Comments

@ReggieMarr
Copy link

F` version v3.1.1
****

Problem Description

Files generated by fpp tools doesn't produce the format string correctly and so the last member of a string doesn't show up as expected. For example

The take the following struct defined in fpp:

  enum CMD_STATUS : U16 {
    NA = 0,
    ACK = 0x5,
    NOT_ACK = 0x6,
    BUSY = 0x7,
    NCE = 0x8,
    STACK_FULL = 0x9,
    TEMP_NOT_ACC = 0x10
  };

  constant ESUP_HEADER_ID = 0x50555345

# NOTE that in byte form it will be represented with LE
  struct EsupPacketHeader {
    HeaderId: U32
    ModuleId: U16
    DataLength: U16
    CmdStatus: CMD_STATUS
  } default {HeaderId = ESUP_HEADER_ID, CmdStatus=CMD_STATUS.NA}


    struct EsupStatusGet {
        Header: EsupPacketHeader
        CmdId: EsupCmdId
        TypeId: U16
        SystemState: U8 @< 1,2,3,4 (1 byte unsigned char value)
        StatusFlags: U8 @< 1 byte unsigned char value
        Reserved: U16 @< 2 byte unsigned short value
        CpuTemperature: F32 @< -40 to 125 °C (4 byte float value)
        FirmwareVersion: U32 @< firmware version (4 byte unsigned int value)
    } default {CmdId = EsupCmdId.ConfGet, TypeId = EsupCmdType.StatusRep}

I then go to print out the contents like so:

static bool receiveEsupStatusResponse(int serialPort, EsupCmdId cmdId, boost::span<BYTE, GET_PADDED_SIZE(EsupStatusGet::SERIALIZED_SIZE)> txBuff) {
        // Wait for a reply
        EsupStatusGet cmdResult;

        size_t bytesRead = read(serialPort, txBuff.data(), txBuff.size());
        if (bytesRead > 0) {
            FW_CHECK(bytesRead <= txBuff.size(), "Error deserializing response", return false; );
            LE_ExternalDeSerializeBuffer responseBuff(txBuff.data(), bytesRead);
            cmdResult.deserialize(responseBuff);
            Fw::String ackString;
            cmdResult.toString(ackString);
            std::cout << std::string(ackString.toChar()) << std::endl;
        } else {
            std::cout << "No reply received." << std::endl;
        }

        return true;
  }

I get the following:

(Header = (HeaderId = 1347769157, ModuleId = 8203, DataLength = 0, CmdStatus = ), CmdId = ConfGet, TypeId = 0, SystemState = 162, StatusFlags = 187, Reserved = 53517, CpuTemperature = 0, FirmwareVersion = )

Where I would normally expect to see something like this (the actual values don't matter for these purposes just that there is something to print):

(Header = (HeaderId = 1347769157, ModuleId = 8203, DataLength = 0, CmdStatus = ACK ), CmdId = ConfGet, TypeId = 0, SystemState = 162, StatusFlags = 187, Reserved = 53517, CpuTemperature = 0, FirmwareVersion = 102444)

I've found this is consistent across pretty much all the fpp serializable objects and it really comes down to the last member of the struct doesn't have a format string generated along with it

So for example we see with the header type the following gets generated:

void EsupPacketHeader::toString(Fw::StringBase& text) const {

    static const char * formatString =
       "("
       "HeaderId = %u, "
       "ModuleId = %u, "
       "DataLength = %u, "
       "CmdStatus = "
       ")";

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


    Fw::String CmdStatusStr;
    this->m_CmdStatus.toString(CmdStatusStr);

    char outputString[FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE];
    (void)snprintf(outputString,FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE,formatString
       ,this->m_HeaderId
       ,this->m_ModuleId
       ,this->m_DataLength
       ,CmdStatusStr.toChar()
    );
    outputString[FW_SERIALIZABLE_TO_STRING_BUFFER_SIZE-1] = 0; // NULL terminate

    text = outputString;
}

With the CmdStatus missing the "%s".

I'm not really sure what the source of the error is since the xml seems to be fine:

<serializable namespace="FlightComputer" name="EsupPacketHeader">
  <import_enum_type>FlightComputer/TransmitterInterface/CMD_STATUSEnumAi.xml</import_enum_type>
  <members>
    <member name="HeaderId" type="U32" format="%u">
      <default>1347769157</default>
    </member>
    <member name="ModuleId" type="U16" format="%u">
      <default>0</default>
    </member>
    <member name="DataLength" type="U16" format="%u">
      <default>0</default>
    </member>
    <member name="CmdStatus" type="FlightComputer::CMD_STATUS" format="%s">
      <default>FlightComputer::CMD_STATUS::NA</default>
    </member>
  </members>
</serializable>

I took a look in array_cpp.py and array_cpp.tmpl but couldn't make sense of the issue there.

If I can get some help on this that'd be much appreciated.

@ReggieMarr ReggieMarr added the bug label May 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant