Maps¶
Introduction¶
A FSTR::Map
is analogous to the Wiring HashMap
class, allowing content to be indexed using
a key value.
The Map contains an array of FSTR::MapPair
structures:
struct MapPair<KeyType, ContentType> {
KeyType key_;
ContentType* content_;
};
KeyType
can be any simple type such as char
, int
, float
, enum
etc.
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.
Example: int ⇒ String¶
Here’s a basic example using integer keys:
#include <FlashString/Map.hpp>
IMPORT_FSTR(content1, PROJECT_DIR "/files/index.html");
IMPORT_FSTR(content2, PROJECT_DIR "/files/favicon.html");
DEFINE_FSTR_MAP(intmap, int, FSTR::String,
{35, &content1},
{180, &content2}
);
We can now do this:
void printValue(int key)
{
auto value = intmap[key];
if(value) {
Serial.printf("Found '%u' in map, containing %u chars\n", value.key(), value.content().length());
Serial.println(value.printer());
} else {
Serial.printf("Couldn't find '%u' in map\n", key);
}
}
Example: String ⇒ String¶
Both the key and the content are stored as Strings:
#include <FlashString/Map.hpp>
DEFINE_FSTR_LOCAL(key1, "index.html");
DEFINE_FSTR_LOCAL(key2, "favicon.ico");
IMPORT_FSTR(content1, PROJECT_DIR "/files/index.html");
IMPORT_FSTR(content2, PROJECT_DIR "/files/favicon.html");
DEFINE_FSTR_MAP(fileMap, FlashString, FlashString,
{&key1, &content1},
{&key2, &content2},
);
We can now do this:
void onFile(HttpRequest& request, HttpResponse& response)
{
String fileName = request.uri.getRelativePath();
auto& value = fileMap[fileName];
if(value) {
// Found
Serial.printf("Found '%s' in fileMap\n", String(value.key()).c_str());
auto stream = new FlashMemoryStream(value);
response.sendDataStream(stream, ContentType::fromFullFileName(fileName));
} else {
Serial.printf("File '%s' not found\n", fileName.c_str());
}
}
Note
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__intmap PROGMEM = {
{16},
{35, &content1},
{180, &content2},
};
const Map<int, String>& intmap = __fstr__intmap.object.as<Map<int, String>>();
Note: FSTR::
namespace qualifier omitted for clarity.
Usually, each MapPair is 8 bytes, but if the key is a double or int64 it would be 12 bytes.
Macros¶
-
DEFINE_FSTR_MAP
(name, KeyType, ContentType, ...)¶
-
DEFINE_FSTR_MAP_LOCAL
(name, KeyType, ContentType, ...)¶ Like DEFINE_FSTR_MAP except reference is declared static constexpr.
-
DEFINE_FSTR_MAP_SIZED
(name, KeyType, ContentType, size, ...)¶
-
DEFINE_FSTR_MAP_SIZED_LOCAL
(name, KeyType, ContentType, size, ...)¶ Like DEFINE_FSTR_MAP_SIZED except reference is declared static.
-
DEFINE_FSTR_MAP_DATA
(name, KeyType, ContentType, ...)¶ Define a Map data structure.
- Note
- Size will be calculated
- Parameters
name
: Name of data structureKeyType
: Integral type to use for keyContentType
: Object type to declare for content...
: List of MapPair definitions { key, &content }
-
DEFINE_FSTR_MAP_DATA_SIZED
(name, KeyType, ContentType, size, ...)¶ Define a Map data structure, specifying the number of elements.
- Parameters
name
: Name of data structureKeyType
: Integral type to use for keyContentType
: Object type to declare for contentsize
: Number of elements...
: List of MapPair definitions { key, &content }
-
const Pair
FSTR::Map
::
valueAt
(unsigned index) const¶ Get a map entry by index, if it exists.
- Note
- Result validity can be checked using if()
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<!std::is_class<T>::value, int>::typeFSTR::Map
::
indexOf
(const TRefKey &key) const¶ Lookup an integral key and return the index.
- Parameters
key
: Key to locate, must be compatible with KeyType for equality comparison
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<std::is_same<T, String>::value, int>::typeFSTR::Map
::
indexOf
(const TRefKey &key, bool ignoreCase = true) const¶ Lookup a String key and return the index.
- Parameters
key
:ignoreCase
: Whether search is case-sensitive (default: true)
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey>
const PairFSTR::Map
::
operator[]
(const TRefKey &key) const¶ Lookup a key and return the entry, if found.
- Note
- Result validity can be checked using if()
- Parameters
key
:
-
MapPrinter<Map>
FSTR::Map
::
printer
() const¶ Returns a printer object for this array.
- Note
- ElementType must be supported by Print
-
DECLARE_FSTR_MAP
(name, KeyType, ContentType)¶ Declare a global Map& reference.
- Note
- Use DEFINE_FSTR_MAP to instantiate the global object
- Parameters
name
:KeyType
: Integral type to use for keyContentType
: Object type to declare for content
-
template <typename KeyType, class ContentType, class Pair = MapPair<KeyType, ContentType>>
classMap
: public FSTR::Object<Map<KeyType, ContentType>, Pair>¶ - #include <Map.hpp>
Class template to access an associative map.
- Template Parameters
KeyType
:ContentType
:
Public Types
-
template<>
usingIterator
= ObjectIterator<Map<KeyType, ContentType>, Pair>¶
Public Functions
-
const Pair
valueAt
(unsigned index) const Get a map entry by index, if it exists.
- Note
- Result validity can be checked using if()
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<!std::is_class<T>::value, int>::typeindexOf
(const TRefKey &key) const Lookup an integral key and return the index.
- Parameters
key
: Key to locate, must be compatible with KeyType for equality comparison
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<std::is_same<T, String>::value, int>::typeindexOf
(const TRefKey &key, bool ignoreCase = true) const Lookup a String key and return the index.
- Parameters
key
:ignoreCase
: Whether search is case-sensitive (default: true)
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey>
const Pairoperator[]
(const TRefKey &key) const Lookup a key and return the entry, if found.
- Note
- Result validity can be checked using if()
- Parameters
key
:
-
MapPrinter<Map>
printer
() const Returns a printer object for this array.
- Note
- ElementType must be supported by Print
-
size_t
printTo
(Print &p) const
-
Iterator
begin
() const
-
Iterator
end
() const
-
size_t
length
() const Get the length of the content in elements.
-
int
indexOf
(const ValueType &value) const
-
Pair
operator[]
(unsigned index) const Array operator[].
-
size_t
elementSize
() const
-
const Pair *
data
() const
-
size_t
read
(size_t index, Pair *buffer, size_t count) const¶ Read content into RAM.
- Parameters
index
: First element to readbuffer
: Where to store datacount
: How many elements to read
- Return Value
size_t
: Number of elements actually read
-
size_t
read
(size_t offset, void *buffer, size_t count) const Read contents of a String into RAM.
- Parameters
offset
: Zero-based offset from start of flash data to start readingbuffer
: Where to store datacount
: How many bytes to read
- Return Value
size_t
: Number of bytes actually read
-
size_t
readFlash
(size_t index, Pair *buffer, size_t count) const¶ Read content into RAM,using
flashmem_read()
- Parameters
index
: First element to readbuffer
: Where to store datacount
: How many elements to read
- Return Value
size_t
: Number of elements actually read
-
size_t
readFlash
(size_t offset, void *buffer, size_t count) const Read contents of a String into RAM, using flashread()
PROGMEM data is accessed via the CPU data cache, so to avoid degrading performance you can use this method to read data directly from flash memory. This is appropriate for infrequently accessed data, especially if it is large. For example, if storing content using
IMPORT_FSTR
instead of SPIFFS then it is generally better to avoid contaminating the cache.- See
- See also
FlashMemoryStream
class. - Parameters
offset
: Zero-based offset from start of flash data to start readingbuffer
: Where to store datacount
: How many bytes to read
- Return Value
size_t
: Number of bytes actually read
-
size_t
size
() const Get the object data size in bytes.
- Note
- Always an integer multiple of 4 bytes
-
template <class ObjectType>
constexpr const ObjectType &as
() const Cast to a different object type.
- Note
- example:
fstr.as<Array<int>>();
-
bool
isCopy
() const
Public Members
-
uint32_t
flashLength_
Public Static Functions
-
static const Map<KeyType, ContentType> &
empty
() Return an empty object which evaluates to null.
-
template <typename KeyType, class ContentType>
classMapPair
¶ - #include <MapPair.hpp>
describes a pair mapping key => data for a specified key type
- Template Parameters
KeyType
: Integral, floating point, enum or StringContentType
: Object type to use for content
Public Types
-
template<>
typedef void (MapPair
::*IfHelperType
)() const¶
Public Functions
-
void
IfHelper
() const¶
-
operator IfHelperType
() const¶ Provides bool() operator to determine if Pair is valid.
-
template <typename T = KeyType>
std::enable_if<!std::is_class<T>::value, KeyType>::typekey
() const¶ Get the key (non-class key types)
-
template <typename T = KeyType>
std::enable_if<std::is_same<T, String>::value, const KeyType&>::typekey
() const Get the key (String key type)
-
const ContentType &
content
() const¶ Accessor to get a reference to the content.
-
operator const ContentType&
() const¶
-
operator WString
() const¶
-
size_t
printTo
(Print &p) const¶
Class Templates¶
-
template <typename KeyType, class ContentType, class Pair = MapPair<KeyType, ContentType>>
classMap
: public FSTR::Object<Map<KeyType, ContentType>, Pair> Class template to access an associative map.
- Template Parameters
KeyType
:ContentType
:
Public Types
-
template<>
usingIterator
= ObjectIterator<Map<KeyType, ContentType>, Pair>
Public Functions
-
const Pair
valueAt
(unsigned index) const Get a map entry by index, if it exists.
- Note
- Result validity can be checked using if()
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<!std::is_class<T>::value, int>::typeindexOf
(const TRefKey &key) const Lookup an integral key and return the index.
- Parameters
key
: Key to locate, must be compatible with KeyType for equality comparison
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey, typename T = KeyType>
std::enable_if<std::is_same<T, String>::value, int>::typeindexOf
(const TRefKey &key, bool ignoreCase = true) const Lookup a String key and return the index.
- Parameters
key
:ignoreCase
: Whether search is case-sensitive (default: true)
- Return Value
int
: If key isn’t found, return -1
-
template <typename TRefKey>
const Pairoperator[]
(const TRefKey &key) const Lookup a key and return the entry, if found.
- Note
- Result validity can be checked using if()
- Parameters
key
:
-
MapPrinter<Map>
printer
() const Returns a printer object for this array.
- Note
- ElementType must be supported by Print
-
size_t
printTo
(Print &p) const
-
Iterator
begin
() const
-
Iterator
end
() const
-
size_t
length
() const Get the length of the content in elements.
-
int
indexOf
(const ValueType &value) const
-
Pair
operator[]
(unsigned index) const Array operator[].
-
size_t
elementSize
() const
-
const Pair *
data
() const
-
size_t
read
(size_t index, Pair *buffer, size_t count) const Read content into RAM.
- Parameters
index
: First element to readbuffer
: Where to store datacount
: How many elements to read
- Return Value
size_t
: Number of elements actually read
-
size_t
read
(size_t offset, void *buffer, size_t count) const Read contents of a String into RAM.
- Parameters
offset
: Zero-based offset from start of flash data to start readingbuffer
: Where to store datacount
: How many bytes to read
- Return Value
size_t
: Number of bytes actually read
-
size_t
readFlash
(size_t index, Pair *buffer, size_t count) const Read content into RAM,using
flashmem_read()
- Parameters
index
: First element to readbuffer
: Where to store datacount
: How many elements to read
- Return Value
size_t
: Number of elements actually read
-
size_t
readFlash
(size_t offset, void *buffer, size_t count) const Read contents of a String into RAM, using flashread()
PROGMEM data is accessed via the CPU data cache, so to avoid degrading performance you can use this method to read data directly from flash memory. This is appropriate for infrequently accessed data, especially if it is large. For example, if storing content using
IMPORT_FSTR
instead of SPIFFS then it is generally better to avoid contaminating the cache.- See
- See also
FlashMemoryStream
class. - Parameters
offset
: Zero-based offset from start of flash data to start readingbuffer
: Where to store datacount
: How many bytes to read
- Return Value
size_t
: Number of bytes actually read
-
size_t
size
() const Get the object data size in bytes.
- Note
- Always an integer multiple of 4 bytes
-
template <class ObjectType>
constexpr const ObjectType &as
() const Cast to a different object type.
- Note
- example:
fstr.as<Array<int>>();
-
bool
isCopy
() const
Public Members
-
uint32_t
flashLength_
Public Static Functions
-
static const Map<KeyType, ContentType> &
empty
() Return an empty object which evaluates to null.
-
template <typename KeyType, class ContentType>
classMapPair
describes a pair mapping key => data for a specified key type
- Template Parameters
KeyType
: Integral, floating point, enum or StringContentType
: Object type to use for content
Public Types
-
template<>
typedef void (MapPair
::*IfHelperType
)() const
Public Functions
-
void
IfHelper
() const
-
operator IfHelperType
() const Provides bool() operator to determine if Pair is valid.
-
template <typename T = KeyType>
std::enable_if<!std::is_class<T>::value, KeyType>::typekey
() const Get the key (non-class key types)
-
template <typename T = KeyType>
std::enable_if<std::is_same<T, String>::value, const KeyType&>::typekey
() const Get the key (String key type)
-
const ContentType &
content
() const Accessor to get a reference to the content.
-
operator const ContentType&
() const
-
operator WString
() const
-
size_t
printTo
(Print &p) const
Public Static Functions
-
static const MapPair
empty
() Get an empty Pair object, identifies as invalid when lookup fails.