Skip to content

Commit 98fda8b

Browse files
committed
Review and update documentation.
1 parent ad3215e commit 98fda8b

12 files changed

+192
-109
lines changed

CONTRIBUTING.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Contributing to FlashString
2+
3+
If you make any modifications or additions to this library, please consider sharing them
4+
so that others may benefit.
5+
6+
If you have an idea but not sure how to implement it, raise an issue.
7+
8+
You can submit changes via [GitHub Pull Requests](https://github.com/mikee47/FlashString/pulls).
9+
10+
Please consider the following elements as part of your PR:
11+
12+
1. Unit testing. Does the existing test application cover your usage?
13+
If not, add the required test cases or a new module, if appropriate.
14+
2. Stick to the library conventions and avoid declaring multiple classes in a single file.
15+
3. Use clang-format in "file" mode to format the code
16+
17+
Thank you!

SUPPORT.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# FlashString Support
2+
3+
## Documentation
4+
5+
The documentation for this library is built as part of Sming.
6+
You can find the current version here:
7+
8+
https://sming.readthedocs.io/en/latest/_inc/Sming/Components/FlashString/index.html
9+
10+
Note that it's also fully searchable.
11+
12+
13+
## Issues
14+
15+
If you are having trouble using the library, it may be because:
16+
17+
- There is a bug in your code
18+
- There is a bug in the library
19+
- The documentation is not clear
20+
- The library is not appropriate for your application
21+
22+
Triage:
23+
24+
1. Please read the documentation!
25+
2. Check any outstanding or previous [Issues on GitHub](https://github.com/mikee47/FlashString/issues)
26+
3. Create a [new issue on GitHub]
27+
(https://github.com/mikee47/FlashString/issues/new).
28+
29+
Please consider your question carefully when raising an issue:
30+
31+
* Good title
32+
* Short description of the problem
33+
* Are you using Linux or Windows?
34+
* Is the problem reproducible in the Host Emulator, or does it only present on actual hardware?
35+
* If appropriate, a brief code example to demonstrate the problem
36+
* Compiler output
37+
38+
Remember, if you don't speak up, we can't help!

array.rst

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Arrays
66
Introduction
77
------------
88

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

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

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

22+
2223
.. note::
2324

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

2829
This also avoids ambiguity between implicit WString conversions.
2930

31+
There are some Print helper functions in the library you can use::
32+
33+
FSTR::println(Serial, myDoubleArray);
34+
35+
These are templated so will handle both simple data types and Objects.
36+
3037
You can share Arrays between translation units by declaring it in a header::
3138

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

56-
Each row is a fixed size. The ``TableRow`` class is provided to simplify this::
63+
Each row is a fixed size. The ``TableRow`` class template is provided to simplify this::
5764

5865
#include <FlashString/Table.hpp>
5966

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

6875

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

7178

7279
Additional Macros

changelog.rst

+10-16
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ Change Log
44
Sming 3.7.0
55
-----------
66

7-
FlashString was first introduced in Sming 3.7.0 on 17 November 2018, as a single file in the Wiring directory.
8-
Other than bugfixes and Host Emulator support it hasn't had any significant updates.
9-
107
Here's the PR summary from the original repository. The 'pull-request' links are rendered during Sming documentation build.
118

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

56+
Sming 4.0.1
57+
-----------
58+
5959
FlashString has been expanded from a single file into its own Component library to:
6060

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

7071
Change summary:
7172

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

map.rst

+27-18
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The Map contains an array of ``MapPair`` structures::
1717
};
1818

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

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

35-
DEFINE_FSTR_MAP(intmap, int, FlashString, {35, &content1}, {180, &content2} );
36-
37-
The macro produces code similar to this::
38-
39-
const struct {
40-
ObjectBase object;
41-
MapPair<int, String> data[2];
42-
} fstr_data_intmap PROGMEM = {
43-
{2},
35+
DEFINE_FSTR_MAP(intmap, int, FSTR::String,
4436
{35, &content1},
45-
{180, &content2},
46-
};
47-
const Map<int, String>& intmap = fstr_data_intmap.object.as<Map<int, String>>();
48-
49-
Note: ``FSTR::`` namespace qualifier omitted for clarity.
37+
{180, &content2}
38+
);
5039

5140
We can now do this::
5241

@@ -62,7 +51,7 @@ We can now do this::
6251
}
6352

6453

65-
Example: String -> String
54+
Example: String => String
6655
-------------------------
6756

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

9887
.. note::
9988

100-
As with Vector<String>, Map<String, ...> performs lookups without case-sensitivity.
89+
As with ``Vector<String>``, ``Map<String, ...>`` lookups are by default case-insensitive.
90+
91+
If you require a case-sensitive lookup, use the ``indexOf`` method with ``ignoreCase = false``.
92+
93+
94+
Structure
95+
---------
96+
97+
The macro in the first example above produces a structure like this::
98+
99+
constexpr const struct {
100+
ObjectBase object;
101+
MapPair<int, String> data[2];
102+
} fstr_data_intmap PROGMEM = {
103+
{16},
104+
{35, &content1},
105+
{180, &content2},
106+
};
107+
const Map<int, String>& intmap = fstr_data_intmap.object.as<Map<int, String>>();
108+
109+
Note: ``FSTR::`` namespace qualifier omitted for clarity.
101110

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

104113

105114
Additional Macros

object.rst

+16-12
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ Objects
66
Introduction
77
------------
88

9-
An ``Object`` is a class template with array-like behaviour and is used to implement
10-
the four classes in the library:
9+
An ``Object`` is a class template with array-like behaviour, though it is not used directly.
10+
11+
Instead, use one of the four classes in the library:
1112

1213
- String
1314
- Array
@@ -42,6 +43,9 @@ disrupting the cache. The ``Stream`` class (alias FlashMemoryStream) does this b
4243
Object Internals
4344
----------------
4445

46+
This section provides some examples of how structures are created, but in normal use you
47+
should use the provided macros as they simplify the task and include structure validity checks.
48+
4549
``ObjectBase`` is a non-template
4650
`POD <https://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/7189821>`__
4751
base class, and looks like this (methods omitted)::
@@ -104,35 +108,35 @@ Here's a somewhat contrived example to demonstrate::
104108

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

107-
To permit aggregate initialization, ObjectBase cannot have any user-defined constructors
108-
which is why we always cast to an Object reference which has the necessary copy constructors::
109-
110-
auto myCopy = flashHelloData.object.as<FSTR::String>();
111-
Serial.print("myCopy.length() = ");
112-
Serial.println(myCopy.length());
113-
114111

115112
Aggregate initialization
116113
------------------------
117114

118115
We use `aggregate initialization <https://en.cppreference.com/w/cpp/language/aggregate_initialization>`__
119116
to set up the structures so the data is fixed at link time without any constructor or initialiser functions.
120117

121-
This means classes cannot have::
118+
This means classes cannot have:
122119

123120
- user-provided constructors
124121
- brace-or-equal-initializers for non-static data members
125122
- private or protected non-static data members
126123
- virtual functions
127124
- base classes (until C++17)
128125

129-
This is why we use ObjectBase.
126+
This is why ObjectBase is used for data structures.
127+
We work using an ``Object`` class template as it provides the necessary constructors::
128+
129+
auto myCopy = flashHelloData.object.as<FSTR::String>();
130+
Serial.print("myCopy.length() = ");
131+
Serial.println(myCopy.length());
132+
133+
The macros create an appropriate Object reference for you.
130134

131135

132136
Structure checks
133137
----------------
134138

135-
The FlashString construction macros all include a sanity check to ensure the initialization is
139+
The construction macros include a sanity check to ensure the initialization is
136140
truly just Plain Old Data, without any hidden initialisers.
137141

138142
You may encounter one of the following errors during compilation:

src/String.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ bool String::equals(const String& str) const
5151
return memcmp_aligned(data(), str.data(), length()) == 0;
5252
}
5353

54-
/* Arduino String support */
54+
/* Wiring String support */
5555

5656
String::operator WString() const
5757
{

src/include/FlashString/String.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "Object.hpp"
2525
#include "StringPrinter.hpp"
2626

27-
// Arduino String - this file is included from WString.h so define required types only
27+
// Wiring String - this file is included from WString.h so define required types only
2828
class String;
2929
class __FlashStringHelper;
3030
typedef const __FlashStringHelper* flash_string_t;

0 commit comments

Comments
 (0)