Objects
Introduction
An FSTR::Object
is a class template with array-like behaviour, though it is not used directly.
Instead, use one of the four classes in the library:
Each type has its own set of macros for easy data construction, and creation of the appropriate Object class which may then be used directly.
Macros follow the same pattern:
DEFINE_FSTR_*
Creates a static data structure with an associated Object reference. The _LOCAL variant makes the reference
static constexpr
.DECLARE_FSTR_*
Use this in a header to declare an Object reference so it can be used across translation units.
Created symbols are C++ and adopt any enclosing namespaced.
Reading Object content
To read parts of an Object, use the FSTR::Object::read()
method.
If the data isn’t used very often, use the FSTR::Object::readFlash()
method instead as it avoids
disrupting the cache. The FSTR::Stream
class (alias FlashMemoryStream
) does this by default.
Object Internals
This section provides some examples of how structures are created, but in normal use you should use the provided macros as they simplify the task and include structure validity checks.
FSTR::ObjectBase
is a non-template
POD
base class, and looks like this (methods omitted):
class ObjectBase {
uint32_t flashLength_;
// uint8_t data[];
};
Attention
flashLength_
must not be accessed directly; use the length()
method instead.
Data structures are created using, for example, DEFINE_FSTR(helloData, "hello")
.
This generates the following layout:
constexpr const struct {
FSTR::String object;
char data[8];
} __fstr__helloData PROGMEM = {
{5},
"hello"
};
const FSTR::String& helloData PROGMEM = __fstr__helloData.object;
Note
The __fstr__
prefix ensures that these structures are stored in flash memory on the esp8266.
When templates are involved the PROGMEM
segment attribute gets discarded.
Do not access __fstr__helloData
directly, it may change in future library versions.
References are an efficient and convenient way to access an Object, and should not consume any memory themselves as the compiler/linker resolves them to the actual object.
However, in practice the Espressif compiler stores a full pointer to most things to support relative addressing, and if the references aren’t declared PROGMEM they’ll consume RAM.
Objects may be cast to a reference of another required type, like this:
auto& arr = helloData.as<FSTR::Array<char>>();
Copy behaviour
Objects cannot be created dynamically, nor can they be copied. Always pass by reference.
Aggregate initialization
We use aggregate initialization to set up the structures so the data is fixed at link time without any constructor or initialiser functions.
This means classes cannot have:
user-provided constructors
brace-or-equal-initializers for non-static data members
private or protected non-static data members
virtual functions
base classes (until C++17)
This is why objects have no constructors or assignment operators.
Structure checks
The construction macros include a sanity check to ensure the initialization is truly just Plain Old Data, without any hidden initialisers.
You may encounter one of the following errors during compilation:
The value of ‘X’ is not usable in a constant expression
FSTR structure not POD
This generally means one or more of the arguments in the initialisation data is not constexpr
.
In testing, this happens with references for global Objects, which of course cannot be constexpr. To fix it, the offending Object needs to be redefined LOCAL.
Macros
-
DEFINE_FSTR_OBJREF(name, object)
-
DEFINE_FSTR_REF(name)
-
DEFINE_FSTR_REF_LOCAL(name)
-
DECLARE_FSTR_OBJECT(name, ObjectType)
Declare a global Object reference.
- Parameters:
name
ObjectType
-
FSTR_DATA_NAME(name)
Provide internal name for generated flash string structures.
-
FSTR_PTR(objref)
Given an Object& reference, return a pointer to the actual object.
Note
This macro was provided for use with old compilers (e.g. GCC 4.8.5) but is no longer required.
- Parameters:
objref
-
FSTR_CHECK_STRUCT(name)
Check structure is POD-compliant and correctly aligned.
-
IMPORT_FSTR_OBJECT(name, ObjectType, file)
Import an object from an external file with reference.
See also
See also
IMPORT_FSTR_DATA
Note
Can only be used at file scope
- Parameters:
name – Name for the object
ObjectType – Object type for reference
file – Absolute path to the file containing the content
-
IMPORT_FSTR_OBJECT_LOCAL(name, ObjectType, file)
Like IMPORT_FSTR_OBJECT except reference is declared static constexpr.
Class Template
-
template<class ObjectType, typename ElementType>
class Object : public FSTR::ObjectBase Base class template for all types.
- Template Parameters:
ObjectType – The object type actually being instantiated
ElementType –
Public Functions
-
inline constexpr size_t length() const
Get the length of the content in elements.
-
inline ElementType operator[](unsigned index) const
Array operator[].
-
inline size_t read(size_t index, ElementType *buffer, size_t count) const
Read content into RAM.
- Parameters:
index – First element to read
buffer – Where to store data
count – How many elements to read
- Return values:
size_t – Number of elements actually read
-
inline size_t readFlash(size_t index, ElementType *buffer, size_t count) const
Read content into RAM,using
flashmem_read()
- Parameters:
index – First element to read
buffer – Where to store data
count – How many elements to read
- Return values:
size_t – Number of elements actually read
Public Static Functions
-
static inline constexpr const ObjectType &empty()
Return an empty object which evaluates to null.