Skip to content

Commit

Permalink
Review and update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
mikee47 committed Jun 11, 2024
1 parent b101263 commit a44b584
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 67 deletions.
4 changes: 2 additions & 2 deletions map.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ Structure
The macro in the first example above produces a structure like this::

constexpr const struct {
ObjectBase object;
Map<MapPair<int, String>> object;
MapPair<int, String> data[2];
} __fstr__intmap PROGMEM = {
{16},
{35, &content1},
{180, &content2},
};
const Map<int, String>& intmap = __fstr__intmap.object.as<Map<int, String>>();
const Map<int, String>& intmap PROGMEM = __fstr__intmap.object;

Note: ``FSTR::`` namespace qualifier omitted for clarity.

Expand Down
40 changes: 17 additions & 23 deletions object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,30 +59,35 @@ base class, and looks like this (methods omitted)::

``flashLength_`` must not be accessed directly; use the ``length()`` method instead.

Data structures are created like this::
Data structures are created using, for example, ``DEFINE_FSTR(helloData, "hello")``.
This generates the following layout::

constexpr const struct {
ObjectBase object;
FSTR::String object;
char data[8];
} flashHelloData PROGMEM = {
} __fstr__helloData PROGMEM = {
{5},
"hello"
};
const FSTR::String& helloData PROGMEM = __fstr__helloData.object;

The ``object`` field may then be cast to a reference of the required type, like this::
.. note::

auto& str = flashHelloData.object.as<FSTR::String>();
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.

If you want to access it as an array, do this::

auto& arr = str.as<FSTR::Array<char>>();
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 resolve them to the actual object.
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
--------------
Expand All @@ -105,16 +110,7 @@ This means classes cannot have:
- virtual functions
- base classes (until C++17)

This is why :cpp:class:`FSTR::ObjectBase` is used to define data structures.

Classes created using the :cpp:class:`FSTR::Object` template ensures the necessary constructors
are available to do this::

auto myCopy = flashHelloData.object.as<FSTR::String>();
Serial.print("myCopy.length() = ");
Serial.println(myCopy.length());

The macros create an appropriate Object& reference for you.
This is why objects have no constructors or assignment operators.


Structure checks
Expand All @@ -129,12 +125,10 @@ You may encounter one of the following errors during compilation:
- FSTR structure not POD

This generally means one or more of the arguments in the initialisation data is not ``constexpr``.
Most compilers are quite relaxed about this but ``GCC 4.8.5`` is particularly thick.

In testing, this happens with references for global Objects, which of course cannot be constexpr.
To fix it, the offending Object either needs to be redefined LOCAL, or if the Object data is in
scope (i.e. defined in the same source file) then you can get a direct pointer to it using
the :c:func:`FSTR_PTR` macro.
To fix it, the offending Object needs to be redefined LOCAL.


Macros
------
Expand Down
23 changes: 2 additions & 21 deletions src/include/FlashString/Object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,9 @@
/**
* @brief Given an Object& reference, return a pointer to the actual object
* @param objref
*
* When an Object pointer is required, such when defining entries for a Vector or Map,
* it is usually sufficient to use &objref.
*
* However, some older compilers such as GCC 4.8.5 requires such references to
* be declared constexpr. For example, this fails with `FSTR structure not POD`:
*
* DEFINE_FSTR(globalStringRef, "This creates a global reference");
* DEFINE_VECTOR(myVector, FSTR::String, &globalStringRef);
* ^^^
*
* Global references cannot be declared constexpr, so changing DEFINE_FSTR to DEFINE_FSTR_LOCAL
* will fix the problem.
*
* Another solution is to get a direct pointer to the actual data structure:
*
* DEFINE_VECTOR(myVector, FSTR::String, FSTR_PTR(globalStringRef));
*
* We can only do this of course if the data structure is in scope.
*
* @note This macro was provided for use with old compilers (e.g. GCC 4.8.5) but is no longer required.
*/
#define FSTR_PTR(objref) (&FSTR_DATA_NAME(objref).object)
#define FSTR_PTR(objref) (&objref)

/**
* @brief Check structure is POD-compliant and correctly aligned
Expand Down
4 changes: 2 additions & 2 deletions string.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ This is equivalent to::
Nested Inline Strings
---------------------

It would be really useful to be able to use inline Strings this within nested structures,
It would be really useful to be able to use inline Strings within nested structures,
and this can be done **provided those structures are in RAM**.

.. important:: Inline Strings cannot be used when defining Vectors or Maps.

Here's is a simplified structure we will attempt to initialize::

static const struct {
FlashString* string;
const FlashString* string;
} flashData PROGMEM = { FS_PTR("Inline Flash String") };
Serial.println(*flashData.string);

Expand Down
5 changes: 5 additions & 0 deletions test/app/custom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ class CustomTest : public TestGroup
REQUIRE(customObject.description() == F("Object Description "));
REQUIRE(customObject.content().length() == sizeof(data));
REQUIRE(memcmp_P(data, customObject.content().data(), sizeof(data)) == 0);

static const struct {
const FlashString* string;
} flashData = {FS_PTR("Inline Flash String")};
Serial.println(*flashData.string);
}
};

Expand Down
3 changes: 1 addition & 2 deletions test/app/data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ DEFINE_FSTR_MAP(stringMap, FSTR::String, FSTR::String, {&key1, &FS_content1}, {&

DEFINE_FSTR_MAP(enumMap, MapKey, FSTR::String, {KeyA, &FS_content1}, {KeyB, &FS_content2});

// Note the use of FSTR_PTR(), required for GCC 4.8.5 because stringVector is a global reference and therefore not constexpr
DEFINE_FSTR_MAP(vectorMap, FSTR::String, FSTR::Vector<FSTR::String>, {&key1, FSTR_PTR(stringVector)});
DEFINE_FSTR_MAP(vectorMap, FSTR::String, FSTR::Vector<FSTR::String>, {&key1, &stringVector});

/**
* Speed
Expand Down
8 changes: 0 additions & 8 deletions todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ Benchmark filemap
- File access times
- File transfer times

Implement stream operator <<
For simpler printing. This is a large architectural decision as Sming doesn't have any of this,
neither it seems does Arduino although some libraries add support for it.

The advantage over Print/Printable is that support can be added using template functions
without modifying the classes themselves. Formatting statements can be inserted to customise
the output.


Formatted print output
We have separate argument for Array printing, but if we want to customise the text for each item
Expand Down
9 changes: 9 additions & 0 deletions upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ This library was introduced to Sming in version 4.0.1.
If you are migrating from Sming 3.7.0 or later and have used FlashString in your projects,
some minor changes may be necessary.

Version 2.1
-----------

Support for copied strings was removed to improve portability and performance.
Code simplification allowed use of compilers other than GCC, such as Clang/LLVM.

Code impact is minimal since FlashString objects should be passed by reference or pointer.


FlashString
~~~~~~~~~~~

Expand Down
13 changes: 4 additions & 9 deletions vector.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ Vectors
Introduction
------------

A :cpp:class:`FSTR::Vector` is an array of Object pointers::

struct Vector<ObjectType> {
FSTR::Object object;
ObjectType* entries[];
};
A :cpp:class:`FSTR::Vector` is an array of Object pointers.

A key use for this is the construction of string tables.

Expand Down Expand Up @@ -67,8 +62,8 @@ Structure

The above example generates a structure like this::

const struct {
ObjectBase object;
constexpr const struct {
Vector<String*> object;
String* entries[4];
} __fstr__myTable PROGMEM = {
{16},
Expand All @@ -77,7 +72,7 @@ The above example generates a structure like this::
nullptr,
&str3,
};
const Vector<String>& myTable PROGMEM = __fstr__myTable.as<Vector<String>>();
const Vector<String>& myTable PROGMEM = __fstr__myTable.object;

Note: ``FSTR::`` namespace qualifier omitted for clarity.

Expand Down

0 comments on commit a44b584

Please sign in to comment.