Arduino KVComm  master
Key-Value pair communication library for Arduino
KV_Builder.cpp
Go to the documentation of this file.
1 #ifdef ARDUINO
2 
4 #include <KVComm/include/KVComm/KV_Helpers.hpp> // nextWord, roundUpToWordSizeMultiple
5 
6 #include <AH/STL/limits> // std::numeric_limits
7 #include <AH/STL/memory> // std::make_unique
8 
9 using AH::make_unique;
10 
11 #else
12 
13 #include <KVComm/KV_Builder.hpp>
14 #include <KVComm/KV_Helpers.hpp> // nextWord, roundUpToWordSizeMultiple
15 
16 #include <iomanip> // setw
17 #include <limits> // std::numeric_limits
18 #include <memory> // std::make_unique
19 #include <ostream> // os
20 
21 using std::make_unique;
22 
23 #endif
24 
25 #if defined(ARDUINO) || defined(ARDUINO_TEST)
26 #include <AH/PrintStream/PrintStream.hpp> // <<
27 #endif
28 
29 uint8_t *KV_Builder::writeHeader(const char *key, uint8_t typeID,
30  size_t length) {
31 
32  // Ensure that the length is not too large
34  return nullptr;
35  // Get the length of the key, and ensure it's not zero and not too large
36  size_t keyLen = strlen(key);
37  if (keyLen == 0 || keyLen > std::numeric_limits<uint8_t>::max())
38  return nullptr;
39  // Calculate the length of the entire key-value pair
40  size_t entryLen = roundUpToWordSizeMultiple(keyLen + 1) + 4 +
42  // Ensure that the entry isn't larger than the buffer
43  if (entryLen > maxLen)
44  return nullptr;
45  // Write the metadata
46  bufferwritelocation[0] = keyLen;
47  bufferwritelocation[1] = typeID;
48  bufferwritelocation[2] = length >> 0;
49  bufferwritelocation[3] = length >> 8;
50  // Write the key
51  strcpy((char *) bufferwritelocation + 4, key);
52  // Compute the index where the data is to be written
53  size_t dataStartIndex = 4 + nextWord(keyLen);
54  uint8_t *dataStart = bufferwritelocation + dataStartIndex;
55  // Update the buffer length and pointer
56  maxLen -= entryLen;
57  bufferwritelocation += entryLen;
58  // Write the sentinel null byte if the buffer is not full yet
59  if (maxLen > 0)
60  bufferwritelocation[0] = 0x00; // Null terminate
61  // Return the address to write the data to
62  return dataStart;
63 }
64 
65 // LCOV_EXCL_START
66 
67 static inline char nibbleToHex(uint8_t val) {
68  val &= 0x0F;
69  return val >= 10 ? val + 'A' - 10 : val + '0';
70 }
71 
72 template <class S>
73 static inline void printHex(S &os, uint8_t val) {
74  os << nibbleToHex(val >> 4) << nibbleToHex(val);
75 }
76 
77 template <class S>
78 void printW(S &os, unsigned u, uint8_t w, char fill = ' ') {
79  auto str = make_unique<char[]>(w + 1);
80  str[w] = '\0';
81  char *begin = &str[0];
82  char *end = begin + w - 1;
83  do {
84  *end-- = u % 10 + '0';
85  u /= 10;
86  } while (u > 0 && end >= begin);
87  if (u > 0) {
88  end = begin + w - 1;
89  fill = '*';
90  }
91  while (end >= begin) {
92  *end-- = fill;
93  }
94  os << begin;
95 }
96 
97 template <class S>
98 void print(const KV_Builder &dict, S &os) {
99  for (size_t i = 0; i < dict.getLength(); i += 4) {
100  printW(os, i, 4, ' ');
101  os << " ";
102  for (uint8_t j = 0; j < 4; ++j) {
103  printHex(os, dict.getBuffer()[i + j]);
104  os << ' ';
105  }
106  os << " ";
107  for (uint8_t j = 0; j < 4; ++j) {
108  char c = isprint(dict.getBuffer()[i + j])
109  ? (char) dict.getBuffer()[i + j]
110  : '.';
111  os << c << ' ';
112  }
113  os << '\n';
114  }
115 }
116 
117 template <class S>
118 void printPython(const KV_Builder &dict, S &os) {
119  os << "bytes((\n";
120  for (size_t i = 0; i < dict.getLength(); i += 4) {
121  os << " ";
122  for (uint8_t j = 0; j < 4; ++j) {
123  os << " 0x";
124  printHex(os, dict.getBuffer()[i + j]);
125  os << ",";
126  }
127  os << '\n';
128  }
129  os << "))" << '\n';
130 }
131 
132 #if !defined(ARDUINO) || defined(DOXYGEN)
133 void KV_Builder::print(std::ostream &os) const { ::print(*this, os); }
134 void KV_Builder::printPython(std::ostream &os) const {
135  ::printPython(*this, os);
136 }
137 #endif
138 
139 #if defined(ARDUINO) || defined(ARDUINO_TEST)
140 void KV_Builder::print(Print &os) const { ::print(*this, os); }
141 void KV_Builder::printPython(Print &os) const { ::printPython(*this, os); }
142 #endif
143 
144 // LCOV_EXCL_END
145 
146 KV_Iterator::iterator KV_Builder::find(const char *key) const {
147  KV_Iterator dict = {getBuffer(), getLength()};
148  return dict.find(key);
149 }
KV_Iterator
Class for iterating over a dictionary generated by the KV_Builder, used for parsing and for checking ...
Definition: KV_Iterator.hpp:42
KV_Iterator::find
iterator find(const char *key) const
Find the entry with the given key (iterates over entire dictionary).
Definition: KV_Iterator.cpp:75
KV_Builder
A class for serializing key-value/array data in a dictionary-like container that can be sent to anoth...
Definition: KV_Builder.hpp:107
printPython
void printPython(const KV_Builder &dict, S &os)
Definition: KV_Builder.cpp:118
printW
void printW(S &os, unsigned u, uint8_t w, char fill=' ')
Definition: KV_Builder.cpp:78
KV_Builder::getBuffer
const uint8_t * getBuffer() const
Get the buffer containing the dictionary.
Definition: KV_Builder.hpp:421
KV_Builder::writeHeader
uint8_t * writeHeader(const char *key, uint8_t typeID, size_t length)
Write the header of a new element into the buffer, advance the write pointer, and return a pointer to...
Definition: KV_Builder.cpp:29
nextWord
size_t nextWord(size_t i)
Get the offset of the next 4-byte word.
Definition: KV_Helpers.hpp:18
KV_Builder::printPython
void printPython(std::ostream &os) const
Definition: KV_Builder.cpp:134
KV_Iterator::iterator
Definition: KV_Iterator.hpp:268
printHex
static void printHex(S &os, uint8_t val)
Definition: KV_Builder.cpp:73
KV_Builder::bufferwritelocation
uint8_t * bufferwritelocation
A pointer to the first free/unused byte in the buffer.
Definition: KV_Builder.hpp:394
nibbleToHex
static char nibbleToHex(uint8_t val)
Definition: KV_Builder.cpp:67
print
void print(const KV_Builder &dict, S &os)
Definition: KV_Builder.cpp:98
roundUpToWordSizeMultiple
size_t roundUpToWordSizeMultiple(size_t i)
Round up a size to a multiple of 4-byte words.
Definition: KV_Helpers.hpp:24
PrintStream.hpp
KV_Builder::find
KV_Iterator::iterator find(const char *key) const
Get the element with the given key.
Definition: KV_Builder.cpp:146
KV_Helpers.hpp
Helpers for address manipulation used to layout dictionary entries in memory.
AH::max
constexpr auto max(const T &a, const U &b) -> decltype(a< b ? b :a)
Return the larger of two numbers/objects.
Definition: MinMaxFix.hpp:22
KV_Builder::getLength
size_t getLength() const
Get the length of the used part of the buffer.
Definition: KV_Builder.hpp:425
KV_Builder.hpp
This file contains the KV_Builder class, a key-value pair, dictionary-like container that supports ma...
KV_Builder::maxLen
size_t maxLen
The maximum remaining length that is still free.
Definition: KV_Builder.hpp:391
KV_Builder::print
void print(std::ostream &os) const
Definition: KV_Builder.cpp:133