Map.hpp
Go to the documentation of this file.
1 /****
2  * Map.hpp - Defines the Map class template and associated macros
3  *
4  * Copyright 2019 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the FlashString Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  * @author: Nov 2019 - Mikee47 <mike@sillyhouse.net>
19  *
20  ****/
21 
22 #pragma once
23 
24 #include "Object.hpp"
25 #include "MapPair.hpp"
26 #include "MapPrinter.hpp"
27 #include "ObjectIterator.hpp"
28 
42 #define DECLARE_FSTR_MAP(name, KeyType, ContentType) DECLARE_FSTR_OBJECT(name, DECL((FSTR::Map<KeyType, ContentType>)))
43 
52 #define DEFINE_FSTR_MAP(name, KeyType, ContentType, ...) \
53  static DEFINE_FSTR_MAP_DATA(FSTR_DATA_NAME(name), KeyType, ContentType, __VA_ARGS__); \
54  DEFINE_FSTR_REF_NAMED(name, DECL((FSTR::Map<KeyType, ContentType>)));
55 
59 #define DEFINE_FSTR_MAP_LOCAL(name, KeyType, ContentType, ...) \
60  static DEFINE_FSTR_MAP_DATA(FSTR_DATA_NAME(name), KeyType, ContentType, __VA_ARGS__); \
61  static constexpr DEFINE_FSTR_REF_NAMED(name, DECL((FSTR::Map<KeyType, ContentType>)));
62 
71 #define DEFINE_FSTR_MAP_SIZED(name, KeyType, ContentType, size, ...) \
72  static DEFINE_FSTR_MAP_DATA_SIZED(FSTR_DATA_NAME(name), KeyType, ContentType, size, __VA_ARGS__); \
73  DEFINE_FSTR_REF_NAMED(name, DECL((FSTR::Map<KeyType, ContentType>)));
74 
78 #define DEFINE_FSTR_MAP_SIZED_LOCAL(name, KeyType, ContentType, size, ...) \
79  static DEFINE_FSTR_MAP_DATA_SIZED(FSTR_DATA_NAME(name), KeyType, ContentType, size, __VA_ARGS__); \
80  static constexpr DEFINE_FSTR_REF_NAMED(name, DECL((FSTR::Map<KeyType, ContentType>)));
81 
90 #define DEFINE_FSTR_MAP_DATA(name, KeyType, ContentType, ...) \
91  DEFINE_FSTR_MAP_DATA_SIZED(name, KeyType, ContentType, \
92  (sizeof((const FSTR::MapPair<KeyType, ContentType>[]){__VA_ARGS__}) / \
93  sizeof(FSTR::MapPair<KeyType, ContentType>)), \
94  __VA_ARGS__)
95 
104 #define DEFINE_FSTR_MAP_DATA_SIZED(name, KeyType, ContentType, size, ...) \
105  constexpr const struct { \
106  FSTR::ObjectBase object; \
107  FSTR::MapPair<KeyType, ContentType> data[size]; \
108  } FSTR_PACKED FSTR_ALIGNED name PROGMEM = {{sizeof(name.data)}, {__VA_ARGS__}}; \
109  FSTR_CHECK_STRUCT(name);
110 
111 namespace FSTR
112 {
118 template <typename KeyType, class ContentType, class Pair = MapPair<KeyType, ContentType>>
119 class Map : public Object<Map<KeyType, ContentType>, Pair>
120 {
121 public:
126  const Pair valueAt(unsigned index) const
127  {
128  if(index >= this->length()) {
129  return Pair::empty();
130  }
131 
132  static_assert(offsetof(Pair, content_) == sizeof(uint32_t), "Misaligned MapPair");
133 
134  auto ptr = this->data() + index;
135  return Pair{readValue(&ptr->key_), readValue(&ptr->content_)};
136  }
137 
143  template <typename TRefKey, typename T = KeyType>
144  typename std::enable_if<!std::is_class<T>::value, int>::type indexOf(const TRefKey& key) const
145  {
146  auto p = this->data();
147  auto len = this->length();
148  for(unsigned i = 0; i < len; ++i, ++p) {
149  if(p->key() == key) {
150  return i;
151  }
152  }
153 
154  return -1;
155  }
156 
163  template <typename TRefKey, typename T = KeyType>
164  typename std::enable_if<std::is_same<T, String>::value, int>::type indexOf(const TRefKey& key,
165  bool ignoreCase = true) const
166  {
167  auto p = this->data();
168  auto len = this->length();
169  for(unsigned i = 0; i < len; ++i, ++p) {
170  if(ignoreCase) {
171  if(p->key().equalsIgnoreCase(key)) {
172  return i;
173  }
174  } else if(p->key() == key) {
175  return i;
176  }
177  }
178 
179  return -1;
180  }
181 
187  template <typename TRefKey> const Pair operator[](const TRefKey& key) const
188  {
189  return valueAt(indexOf(key));
190  }
191 
192  /* Arduino Print support */
193 
199  {
200  return MapPrinter<Map>(*this);
201  }
202 
203  size_t printTo(Print& p) const
204  {
205  return printer().printTo(p);
206  }
207 };
208 
209 } // namespace FSTR
210 
void size_t const void * key
Definition: blake2s.h:33
Class template to provide a simple way to print the contents of a Map.
Definition: MapPrinter.hpp:31
Class template to access an associative map.
Definition: Map.hpp:120
std::enable_if< std::is_same< T, String >::value, int >::type indexOf(const TRefKey &key, bool ignoreCase=true) const
Lookup a String key and return the index.
Definition: Map.hpp:164
const Pair operator[](const TRefKey &key) const
Lookup a key and return the entry, if found.
Definition: Map.hpp:187
const Pair valueAt(unsigned index) const
Get a map entry by index, if it exists.
Definition: Map.hpp:126
MapPrinter< Map > printer() const
Returns a printer object for this array.
Definition: Map.hpp:198
size_t printTo(Print &p) const
Definition: Map.hpp:203
std::enable_if<!std::is_class< T >::value, int >::type indexOf(const TRefKey &key) const
Lookup an integral key and return the index.
Definition: Map.hpp:144
Base class template for all types.
Definition: Object.hpp:121
constexpr const size_t length() const
Get the length of the content in elements.
Definition: Object.hpp:168
Provides formatted output to stream.
Definition: Print.h:37
Definition: Array.hpp:108
std::enable_if< sizeof(T)==1, T >::type readValue(const T *ptr)
Read a typed value from flash memory ensuring correct alignment of access.
Definition: Utility.hpp:126