fprime/Os/Console.hpp
Ian Brault 2b65cc83cf
Add new Fw::ConstStringBase type for strings backed by immutable string literals (#4269)
* Add new Fw::StringBase type StaticString for strings backed my immutable literals

* Spellcheck fix

* Add disclaimer comment about use of StaticString

* Refactor the StringBase interface into an immutable ConstStringBase abstract base class and the now mutable StringBase class

* Rename StaticString to ConstExternalString and inherit from ConstStringBase

* Fix typo

* Change references from StringBase to ConstStringBase where applicable

* Updates following review meeting: add missing deserialize function and add new error status, move length function implementation into ConstStringBase so it is not pure virtual

* Clang format fix

* Additional clang-format fixes

* Fix the copy-assignment operator for StringBase not being correctly evaluated

* Clang format fix

* Explicitly delete the Serializable assignment operator and provide a skeleton implementation for RawTimeInterface to appease the compiler

* Revert "Explicitly delete the Serializable assignment operator and provide a skeleton implementation for RawTimeInterface to appease the compiler"

This reverts commit 086d7bcd3ca9c4f6e553d7fc34d0d126a69a165b.

* Move ConstStringBase to separate hpp/cpp files, plus other pull request feedback

* Clang format fix

* Update length implementation for ConstStringBase and ConstExternalString

* Improved asserts in ConstExternalString constructor

Co-authored-by: Rob Bocchino <bocchino@icloud.com>

* Fixed ConstStringBase length implementation

Co-authored-by: Rob Bocchino <bocchino@icloud.com>

* Clang format fix

* Add some UTs for ConstExternalString, fix non-overridden interfaces, and fix ConstStringBase::maxLength asserting for zero capacity strings

* Spell-check fix for ConstExternalString UTs

* Revise length implementation in ConstStringBase

If the capacity is zero, return zero

* Format

---------

Co-authored-by: Ian Brault <ian.r.brault@jpl.nasa.gov>
Co-authored-by: Rob Bocchino <bocchino@icloud.com>
Co-authored-by: Rob Bocchino <bocchino@jpl.nasa.gov>
Co-authored-by: M Starch <LeStarch@googlemail.com>
2025-11-07 09:50:05 -08:00

140 lines
5.6 KiB
C++

// ======================================================================
// \title Os/Console.hpp
// \brief common function definitions for Os::Console
// ======================================================================
#ifndef Os_Console_hpp_
#define Os_Console_hpp_
#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Logger/Logger.hpp>
#include <Os/Console.hpp>
#include <Os/Os.hpp>
namespace Os {
//! \brief Base class for storing implementation specific handle information
struct ConsoleHandle {};
// \brief Interface defining the properties of the console
class ConsoleInterface {
public:
//! \brief Default constructor
ConsoleInterface() = default;
//! \brief Default destructor
virtual ~ConsoleInterface() = default;
//! \brief write message to console
//!
//! Write a message to the console with a bounded size.
//!
//! \param message: raw message to write
//! \param size: size of the message to write to the console
virtual void writeMessage(const CHAR* message, const FwSizeType size) = 0;
//! \brief returns the raw console handle
//!
//! Gets the raw console handle from the implementation. Note: users must include the implementation specific
//! header to make any real use of this handle. Otherwise it will be as an opaque type.
//!
//! \return raw console handle
//!
virtual ConsoleHandle* getHandle() = 0;
//! \brief provide a pointer to a console delegate object
//!
//! This function must return a pointer to a `ConsoleInterface` object that contains the real implementation of
//! the console functions as defined by the implementor. This function must do several things to be considered
//! correctly implemented:
//!
//! 1. Assert that their implementation fits within FW_HANDLE_MAX_SIZE.
//! e.g. `static_assert(sizeof(PosixFileImplementation) <= sizeof Os::File::m_handle_storage,
//! "FW_HANDLE_MAX_SIZE too small");`
//! 2. Assert that their implementation aligns within FW_HANDLE_ALIGNMENT.
//! e.g. `static_assert((FW_HANDLE_ALIGNMENT % alignof(PosixFileImplementation)) == 0, "Bad handle alignment");`
//! 3. If to_copy is null, placement new their implementation into `aligned_placement_new_memory`
//! e.g. `FileInterface* interface = new (aligned_placement_new_memory) PosixFileImplementation;`
//! 4. If to_copy is non-null, placement new using copy constructor their implementation into
//! `aligned_placement_new_memory`
//! e.g. `FileInterface* interface = new (aligned_placement_new_memory) PosixFileImplementation(*to_copy);`
//! 5. Return the result of the placement new
//! e.g. `return interface;`
//!
//! \return result of placement new, must be equivalent to `aligned_placement_new_memory`
//!
static ConsoleInterface* getDelegate(ConsoleHandleStorage& aligned_placement_new_memory,
const ConsoleInterface* to_copy = nullptr);
};
class Console : public ConsoleInterface, public Fw::Logger {
public:
//! \brief Default constructor
Console();
//! \brief Default destructor
~Console();
//! \brief copy constructor that copies the internal representation
Console(const Console& other);
//! \brief assignment operator that copies the internal representation
Console& operator=(const Console& other);
//! \brief write message to console
//!
//! Write a message to the console with a bounded size. This will delegate to the implementation defined write
//! method.
//!
//! \param message: raw message to write
//! \param size: size of the message to write to the console
void writeMessage(const CHAR* message, const FwSizeType size) override;
//! \brief write message to console
//!
//! Write a message to the console as stored as a ConstStringBase type
//!
//! \param message: raw message to write (ConstStringBase)
void writeMessage(const Fw::ConstStringBase& message) override;
//! \brief returns the raw console handle
//!
//! Gets the raw console handle from the implementation. Note: users must include the implementation specific
//! header to make any real use of this handle. Otherwise it will be as an opaque type.
//!
//! \return raw console handle
//!
ConsoleHandle* getHandle() override;
//! \brief write message to console
//!
//! Write a message to the console as stored as a ConstStringBase type
//!
//! \param message: raw message to write (ConstStringBase)
static void write(const Fw::ConstStringBase& message);
//! \brief write message to the global console
//!
//! Write a message to the console with a bounded size. This will delegate to the global singleton
//! implementation.
//!
//! \param message: raw message to write
//! \param size: size of the message to write to the console
static void write(const CHAR* message, const FwSizeType size);
//! \brief initialize singleton
static void init();
//! \brief get a reference to singleton
//! \return reference to singleton
static Console& getSingleton();
private:
// This section is used to store the implementation-defined console handle. To Os::Console and fprime, this type
// is opaque and thus normal allocation cannot be done. Instead, we allow the implementor to store then handle
// in the byte-array here and set `handle` to that address for storage.
alignas(FW_HANDLE_ALIGNMENT) ConsoleHandleStorage m_handle_storage; // Storage for the delegate
ConsoleInterface& m_delegate; //!< Delegate for the real implementation
};
} // namespace Os
#endif