Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
ConfigEntry.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_CONFIGENTRY_HXX_
36#define _OPENLCB_CONFIGENTRY_HXX_
37
38#include <endian.h>
39#include <stdint.h>
40#include <string.h>
41#include <sys/types.h>
42
43#include <functional>
44
46
47namespace openlcb
48{
49
54{
55public:
60 constexpr explicit ConfigReference(unsigned offset)
61 : offset_(offset)
62 {
63 }
64
68 constexpr explicit ConfigReference(const ConfigReference &ref)
69 : offset_(ref.offset())
70 {
71 }
72
73 constexpr unsigned offset() const
74 {
75 return offset_;
76 }
77
78protected:
80 unsigned offset_;
81};
82
85typedef std::function<void(unsigned)> EventOffsetCallback;
86
92{
93public:
95
96 template<typename... Args>
97 static constexpr GroupConfigOptions group_opts(Args... args)
98 {
99 return GroupConfigOptions();
100 }
101
102 static void handle_events(const EventOffsetCallback& fn) {}
103
104protected:
112 template <class T> T raw_read(int fd) const
113 {
114 T ret;
115 repeated_read(fd, &ret, sizeof(T));
116 return ret;
117 }
118
126 template <class T> void raw_write(int fd, const T &value) const
127 {
128 repeated_write(fd, &value, sizeof(T));
129 }
130
137 void repeated_read(int fd, void *buf, size_t size) const;
138
145 void repeated_write(int fd, const void *buf, size_t size) const;
146};
147
150template <class TR> class NumericConfigEntry : public ConfigEntryBase
151{
152public:
154
155
161 static uint8_t endian_convert(uint8_t d)
162 {
163 return d;
164 }
171 static uint16_t endian_convert(uint16_t d)
172 {
173 return be16toh(d);
174 }
181 static uint32_t endian_convert(uint32_t d)
182 {
183 return be32toh(d);
184 }
191 static uint64_t endian_convert(uint64_t d)
192 {
193 return be64toh(d);
194 }
195
202 static int8_t endian_convert(int8_t d)
203 {
204 return d;
205 }
212 static int16_t endian_convert(int16_t d)
213 {
214 return be16toh(d);
215 }
222 static int32_t endian_convert(int32_t d)
223 {
224 return be32toh(d);
225 }
232 static int64_t endian_convert(int64_t d)
233 {
234 return be64toh(d);
235 }
236
242 static constexpr unsigned size()
243 {
244 return sizeof(TR);
245 }
246
247 constexpr unsigned end_offset() const
248 {
249 return offset() + size();
250 }
251
252 static constexpr NumericConfigRenderer config_renderer()
253 {
254 return NumericConfigRenderer("int", size());
255 }
256
263 TR read(int fd) const
264 {
265 return endian_convert(raw_read<TR>(fd));
266 }
267
276 TR read_or_write_trimmed(int fd, TR min_value, TR max_value) {
277 TR value = read(fd);
278 if (value < min_value) {
279 value = min_value;
280 write(fd, value);
281 }
282 if (value > max_value) {
283 value = max_value;
284 write(fd, value);
285 }
286 return value;
287 }
288
298 TR read_or_write_default(int fd, TR min_value, TR max_value, TR def_value)
299 {
300 TR value = read(fd);
301 if (value < min_value || value > max_value)
302 {
303 value = def_value;
304 write(fd, value);
305 }
306 return value;
307 }
308
315 void write(int fd, TR d) const
316 {
318 }
319};
320
329
338
341{
342public:
343 template <typename T>
344 constexpr EventConfigEntry(T t)
346 {
347 }
348
349 static constexpr AtomConfigRenderer config_renderer()
350 {
351 return AtomConfigRenderer("eventid", AtomConfigRenderer::SKIP_SIZE);
352 }
353
354 void handle_events(const EventOffsetCallback& fn) {
355 fn(offset());
356 }
357};
358
362template <unsigned SIZE> class StringConfigEntry : public ConfigEntryBase
363{
364public:
366
367
372 static constexpr unsigned size()
373 {
374 return SIZE;
375 }
376
377 constexpr unsigned end_offset() const
378 {
379 return offset() + size();
380 }
381
382 static constexpr AtomConfigRenderer config_renderer()
383 {
384 return AtomConfigRenderer("string", size());
385 }
386
387 string read(int fd) const
388 {
389 string s(size(), '\0');
390 repeated_read(fd, &s[0], size());
391 size_t real_len = strlen(s.c_str());
392 s.resize(real_len);
393 return s;
394 }
395
396 void write(int fd, string data) const
397 {
398 if (data.size() > size() - 1) {
399 data.resize(size() - 1);
400 }
401 repeated_write(fd, data.c_str(), data.size() + 1);
402 }
403};
404
409template <unsigned SIZE> class BytesConfigEntry : public ConfigEntryBase
410{
411public:
413
414 static_assert(SIZE <= 256, "BytesConfigEntry cannot store longer than 255");
415
421 static constexpr unsigned size()
422 {
423 return SIZE;
424 }
425
426 constexpr unsigned end_offset() const
427 {
428 return offset() + size();
429 }
430
431 static constexpr EmptyGroupConfigRenderer config_renderer()
432 {
433 return EmptyGroupConfigRenderer(size());
434 }
435
436 string read(int fd) const
437 {
438 string s(size(), '\0');
439 repeated_read(fd, &s[0], size());
440 size_t real_len = (unsigned char)s[0];
441 return s.substr(1, real_len);
442 }
443
444 void write(int fd, string data) const
445 {
446 HASSERT(data.size() < size());
447 data.insert(0, 1, data.size());
448 repeated_write(fd, data.data(), data.size());
449 }
450};
451
452} // namespace openlcb
453
454#endif // _OPENLCB_CONFIGENTRY_HXX_
Helper class for rendering an atom data element into the cdi.xml.
Implementation class for internal data bytes configuration entries.
static constexpr unsigned size()
Storage bytes occupied by the instance in the config file.
Base class for individual configuration entries.
void raw_write(int fd, const T &value) const
Writes a given typed variable to the configuration file.
T raw_read(int fd) const
Reads a given typed variable from the configuration file.
void repeated_read(int fd, void *buf, size_t size) const
Performs a reliable read from the given FD.
void repeated_write(int fd, const void *buf, size_t size) const
Performs a reliable write to the given FD.
Class representing a particular location in the configuration space.
unsigned offset_
zero-based offset from the beginning of the configuration file.
constexpr ConfigReference(unsigned offset)
Initializes the config reference from a configuration space offset.
constexpr ConfigReference(const ConfigReference &ref)
Initializes the config reference from an existing config reference.
Implementation class for event ID configuration entries.
Implementation class for the condifuration options of a CDI group element.
Implementation class for numeric configuration entries, templated by the integer type.
static int32_t endian_convert(int32_t d)
Performs endian conversion.
static uint32_t endian_convert(uint32_t d)
Performs endian conversion.
static int16_t endian_convert(int16_t d)
Performs endian conversion.
void write(int fd, TR d) const
Writes the data to the configuration file.
static uint8_t endian_convert(uint8_t d)
Performs endian conversion.
static int64_t endian_convert(int64_t d)
Performs endian conversion.
TR read_or_write_default(int fd, TR min_value, TR max_value, TR def_value)
Reads data from configuration file if the value is valid.
static constexpr unsigned size()
Storage bytes occupied by the instance in the config file.
TR read_or_write_trimmed(int fd, TR min_value, TR max_value)
Reads data from configuration file obeying a specific trimming.
TR read(int fd) const
Reads the data from the configuration file.
static uint64_t endian_convert(uint64_t d)
Performs endian conversion.
static uint16_t endian_convert(uint16_t d)
Performs endian conversion.
static int8_t endian_convert(int8_t d)
Performs endian conversion.
Implementation class for string configuration entries.
static constexpr unsigned size()
Storage bytes occupied by the instance in the config file.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define INHERIT_CONSTEXPR_CONSTRUCTOR(CURRENT_CLASS, BASE_CLASS)
Adds a constexpr constructor to the current class that proxies every argument to the base constructor...
Definition macros.h:205
std::function< void(unsigned)> EventOffsetCallback
Function declaration that will be called with all event offsets that exist in the configuration space...
NumericConfigEntry< uint64_t > Uint64ConfigEntry
Unsigned numeric config entry with 8 bytes width.