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 Nov 21, 2019
1 parent ad3215e commit 98fda8b
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 109 deletions.
17 changes: 17 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Contributing to FlashString

If you make any modifications or additions to this library, please consider sharing them
so that others may benefit.

If you have an idea but not sure how to implement it, raise an issue.

You can submit changes via [GitHub Pull Requests](https://github.com/mikee47/FlashString/pulls).

Please consider the following elements as part of your PR:

1. Unit testing. Does the existing test application cover your usage?
If not, add the required test cases or a new module, if appropriate.
2. Stick to the library conventions and avoid declaring multiple classes in a single file.
3. Use clang-format in "file" mode to format the code

Thank you!
38 changes: 38 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# FlashString Support

## Documentation

The documentation for this library is built as part of Sming.
You can find the current version here:

https://sming.readthedocs.io/en/latest/_inc/Sming/Components/FlashString/index.html

Note that it's also fully searchable.


## Issues

If you are having trouble using the library, it may be because:

- There is a bug in your code
- There is a bug in the library
- The documentation is not clear
- The library is not appropriate for your application

Triage:

1. Please read the documentation!
2. Check any outstanding or previous [Issues on GitHub](https://github.com/mikee47/FlashString/issues)
3. Create a [new issue on GitHub]
(https://github.com/mikee47/FlashString/issues/new).

Please consider your question carefully when raising an issue:

* Good title
* Short description of the problem
* Are you using Linux or Windows?
* Is the problem reproducible in the Host Emulator, or does it only present on actual hardware?
* If appropriate, a brief code example to demonstrate the problem
* Compiler output

Remember, if you don't speak up, we can't help!
13 changes: 10 additions & 3 deletions array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Arrays
Introduction
------------

Supports simple arrays of simple types, such as char, int, double, or POD structures.
Supports arrays of simple types, such as char, int, double, or POD structures (i.e. basic C structures).

The ``Array`` is a class template, so requires an additional ``ElementType`` parameter::

Expand All @@ -19,6 +19,7 @@ The ``Array`` is a class template, so requires an additional ``ElementType`` par
myDoubleArray.printTo(Serial);
Serial.println();


.. note::

Objects do not inherit from Printable because it is a virtual base class.
Expand All @@ -27,6 +28,12 @@ The ``Array`` is a class template, so requires an additional ``ElementType`` par

This also avoids ambiguity between implicit WString conversions.

There are some Print helper functions in the library you can use::

FSTR::println(Serial, myDoubleArray);

These are templated so will handle both simple data types and Objects.

You can share Arrays between translation units by declaring it in a header::

DECLARE_FSTR_ARRAY(table);
Expand All @@ -53,7 +60,7 @@ Simple tables can be implemented using Arrays, like this::
Serial.printf("%f, %f, %f\n", row[0], row[1], row[2]);
}

Each row is a fixed size. The ``TableRow`` class is provided to simplify this::
Each row is a fixed size. The ``TableRow`` class template is provided to simplify this::

#include <FlashString/Table.hpp>

Expand All @@ -66,7 +73,7 @@ Each row is a fixed size. The ``TableRow`` class is provided to simplify this::
table.println();


If you want to create a table with rows of different sizes or types, use a :doc:`vector`.
If you want to create a table with rows of different sizes or types, use a :doc:`Vector <vector>`.


Additional Macros
Expand Down
26 changes: 10 additions & 16 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ Change Log
Sming 3.7.0
-----------

FlashString was first introduced in Sming 3.7.0 on 17 November 2018, as a single file in the Wiring directory.
Other than bugfixes and Host Emulator support it hasn't had any significant updates.

Here's the PR summary from the original repository. The 'pull-request' links are rendered during Sming documentation build.

Thu Sep 20 18:00:58 2018 :pull-request:`1438`
Expand Down Expand Up @@ -56,6 +53,9 @@ Sat Nov 2 13:01:20 2019
Sming version 4.0.0 is due for release next week, and FlashString has proven to be a useful
addition to the toolkit. Time for an upgrade.

Sming 4.0.1
-----------

FlashString has been expanded from a single file into its own Component library to:

1. Improve support for tables and add associative mapping
Expand All @@ -66,23 +66,17 @@ FlashString has been expanded from a single file into its own Component library
6. Make it easier to port to other frameworks (e.g. Arduino)
7. Get it out of Wiring - doesn't really belong there and certainly don't want to clutter up that directory
8. Improve maintainability
9. Fix compatibility with ArduinoJson 6.13.0

Change summary:

- Move FlashString into a separate Component
- Add FlashString::read() and readFlash() methods
- Revise FlashString internals to be more consistent with naming
- Improve FlashString table handling using new `Vector` class
- Revise internals to be more consistent with naming
- Improve table handling using new `Vector` class
- Add associative mapping support with `Map` class
- Investigate alternative structures to allow copy construction. Nope, not going to happen.
Cannot use constructors at all as with global instances produces constructor code which attempts
to write to flashmem. These MUST be vanilla structs to work correctly.
- Revise FlashString structure so it contains only the length,
obtaining data position using pointer arithmetic.
- Revise structures so it contains only the length, obtaining data position using pointer arithmetic.
This fixes an error with GCC 8.2.0 which didn't like accessing zero-length arrays.
- All data structures use the appropriate class as the first element
- Avoids violating any compiler rules
- No need for casting
- Clean way to get at the actual FlashString
- Move FlashString into Component
- Use ObjectBase as the first element in a data structure to allow use of 'safe' static casting,
handled using the `as()` method template
- Documentation!

45 changes: 27 additions & 18 deletions map.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The Map contains an array of ``MapPair`` structures::
};

``KeyType`` can be any simple type such as ``char``, ``int``, ``float``, ``enum`` etc.
It may also be a ``String`` object.
It may also be a ``String`` Object (or, more precisely, ``String*``).

``ContentType`` can be any Object type (String, Array, Vector or Map).
This allows hierarchical structures to be created.
Expand All @@ -32,21 +32,10 @@ Here's a basic example using integer keys::
IMPORT_FSTR(content1, PROJECT_DIR "/files/index.html");
IMPORT_FSTR(content2, PROJECT_DIR "/files/favicon.html");

DEFINE_FSTR_MAP(intmap, int, FlashString, {35, &content1}, {180, &content2} );

The macro produces code similar to this::

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

Note: ``FSTR::`` namespace qualifier omitted for clarity.
{180, &content2}
);

We can now do this::

Expand All @@ -62,7 +51,7 @@ We can now do this::
}


Example: String -> String
Example: String => String
-------------------------

Both the key and the content are stored as Strings::
Expand Down Expand Up @@ -97,9 +86,29 @@ We can now do this::

.. note::

As with Vector<String>, Map<String, ...> performs lookups without case-sensitivity.
As with ``Vector<String>``, ``Map<String, ...>`` lookups are by default case-insensitive.

If you require a case-sensitive lookup, use the ``indexOf`` method with ``ignoreCase = false``.


Structure
---------

The macro in the first example above produces a structure like this::

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

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

The ``indexOf`` method has an extra ``ignoreCase`` parameter, which defaults to ``true``.
Usually, each MapPair is 8 bytes, but if the key is a double or int64 it would be 12 bytes.


Additional Macros
Expand Down
28 changes: 16 additions & 12 deletions object.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ Objects
Introduction
------------

An ``Object`` is a class template with array-like behaviour and is used to implement
the four classes in the library:
An ``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:

- String
- Array
Expand Down Expand Up @@ -42,6 +43,9 @@ disrupting the cache. The ``Stream`` class (alias FlashMemoryStream) does this b
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.

``ObjectBase`` is a non-template
`POD <https://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/7189821>`__
base class, and looks like this (methods omitted)::
Expand Down Expand Up @@ -104,35 +108,35 @@ Here's a somewhat contrived example to demonstrate::

In debug builds, this will throw an assertion. In release builds, you'll get a zero-length object.

To permit aggregate initialization, ObjectBase cannot have any user-defined constructors
which is why we always cast to an Object reference which has the necessary copy constructors::

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


Aggregate initialization
------------------------

We use `aggregate initialization <https://en.cppreference.com/w/cpp/language/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::
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 we use ObjectBase.
This is why ObjectBase is used for data structures.
We work using an ``Object`` class template as it provides the necessary constructors::

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

The macros create an appropriate Object reference for you.


Structure checks
----------------

The FlashString construction macros all include a sanity check to ensure the initialization is
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:
Expand Down
2 changes: 1 addition & 1 deletion src/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ bool String::equals(const String& str) const
return memcmp_aligned(data(), str.data(), length()) == 0;
}

/* Arduino String support */
/* Wiring String support */

String::operator WString() const
{
Expand Down
2 changes: 1 addition & 1 deletion src/include/FlashString/String.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "Object.hpp"
#include "StringPrinter.hpp"

// Arduino String - this file is included from WString.h so define required types only
// Wiring String - this file is included from WString.h so define required types only
class String;
class __FlashStringHelper;
typedef const __FlashStringHelper* flash_string_t;
Expand Down
Loading

0 comments on commit 98fda8b

Please sign in to comment.