nasa / fpp

F Prime Prime: A modeling language for F Prime
https://fprime.jpl.nasa.gov
Apache License 2.0
46 stars 31 forks source link

Minimize use of auto-generated string types in C++ code gen #406

Closed bocchino closed 4 months ago

bocchino commented 4 months ago

When a type string size s appears in FPP, the C++ code generator generates a class StringSize s. These generated string classes appear in array, struct, and port definitions.

This code generation is inefficient and awkward. Instead of generating all these string classes, we should do the following:

  1. When passing or returning a string value by reference, don't use a concrete string type; instead use Fw::StringBase&.
  2. When Fw::StringBase& is passed to a string parameter that has size s, bound the size to s when computing the serialized size or when serializing the bytes.
  3. When allocating a concrete string of size s, (a) declare a char array A of size s and (b) pass A into an instance of an ExternalString class that implements the StringBuffer interface against A. See https://github.com/nasa/fprime/pull/2679. For string arrays, we can have an array of external strings backed by an array of arrays of char.
  4. When computing the static serialized size of an external string (e.g., in sizing a message on the queue), have the code generator fill in the size directly, instead of using the SERIALIZED_SIZE constant. This constant will not exist for external strings, since there is no known static serialized size for this type.

I also note that the current string class generation has a subtle bug, or idiosyncrasy: string size s generates a string type with a buffer of size s. However, F Prime strings are null-terminated when they are stored in buffers (but not when they are serialized), so strings stored into a buffer of size s are truncated to max length s - 1. I think the FPP string size should represent the maximum string length, not the max string length minus one. So the buffer size in the generated code should be s + 1. This way the meaning of the string size is consistent across both cases: storing in a String object and serializing to bytes. It is always the max string length.

This issue supersedes #387.

bocchino commented 4 months ago

So the buffer size in the generated code should be s + 1.

For strings defined in the framework, this is fixed in https://github.com/nasa/fprime/pull/2703. Still working on it for the auto-generated strings.

bocchino commented 4 months ago

I'm rethinking this issue a bit. Completely eliminating auto-generated string classes is challenging, because we need to construct arrays of strings, and because we sometimes need the string representation in the interface. I think we should do the following:

  1. Simplify the auto-generated strings as we have done in the framework code.
  2. Switch as much as possible to using const Fw::StringBase& in the interface.
  3. Where we have to use a generated string type in the interface, make sure that a type alias is available so that user code does not depend on the string size.
  4. Minimize reliance on implicit constructor calls.
  5. Fix the off-by-one error in the buffer sizes for generated strings.
bocchino commented 4 months ago

Superseded by #423.