esp8266ndn
NDN Arduino library for ESP8266 and more
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
name.hpp
Go to the documentation of this file.
1#ifndef NDNPH_PACKET_NAME_HPP
2#define NDNPH_PACKET_NAME_HPP
3
4#include "../core/input-iterator-pointer-proxy.hpp"
5#include "component.hpp"
6
7namespace ndnph {
8
14class Name : public Printable {
15public:
17 explicit Name(const uint8_t* value = nullptr, size_t length = 0) {
18 decodeValue(value, length);
19 }
20
22 template<typename It>
23 explicit Name(Region& region, It first, It last) {
24 static_assert(std::is_base_of<std::forward_iterator_tag,
25 typename std::iterator_traits<It>::iterator_category>::value,
26 "");
27 static_assert(std::is_same<uint8_t, typename std::iterator_traits<It>::value_type>::value, "");
28 size_t length = std::distance(first, last);
29 uint8_t* value = region.alloc(length);
30 if (value != nullptr) {
31 std::copy(first, last, value);
32 decodeValue(value, length);
33 }
34 }
35
37 explicit Name(Region& region, std::initializer_list<uint8_t> value)
38 : Name(region, value.begin(), value.end()) {}
39
49 static Name parse(Region& region, const char* uri) {
50 size_t uriLen = std::strlen(uri);
51 size_t bufLen = 2 * uriLen;
52 uint8_t* buf = region.alloc(bufLen);
53 if (buf == nullptr) {
54 return Name();
55 }
56
57 size_t nComps = 0;
58 ssize_t length = parseUri(buf, bufLen, uri, uriLen, nComps);
59 if (length < 0) {
60 region.free(buf, bufLen);
61 return Name();
62 }
63
64 uint8_t* value = buf + bufLen - length;
65 if (value != buf) {
66 std::copy_backward(buf, buf + length, value + length);
67 region.free(buf, bufLen - length);
68 }
69 return Name(value, length, nComps);
70 }
71
73 explicit operator bool() const {
74 return m_nComps > 0;
75 }
76
77 size_t length() const {
78 return m_length;
79 }
80
81 const uint8_t* value() const {
82 return m_value;
83 }
84
86 size_t size() const {
87 return m_nComps;
88 }
89
91 class Iterator : public Decoder::Iterator {
92 public:
94 using iterator_category = std::input_iterator_tag;
95 using value_type = const Component;
96 using difference_type = std::ptrdiff_t;
99
100 Iterator() = default;
101
102 explicit Iterator(const super& inner)
103 : super(inner) {}
104
106 Component comp;
107 comp.decodeFrom(super::operator*());
108 return comp;
109 }
110
112 return pointer(this->operator*());
113 }
114 };
115
116 Iterator begin() const {
117 return Iterator(Decoder(m_value, m_length).begin());
118 }
119
120 Iterator end() const {
121 return Iterator(Decoder(m_value, m_length).end());
122 }
123
125 Component operator[](int i) const {
126 if (i < 0) {
127 i += m_nComps;
128 }
129 if (isOutOfRange(i)) {
130 return Component();
131 }
132 auto it = begin();
133 std::advance(it, i);
134 return *it;
135 }
136
142 Name slice(int first = 0, int last = 0) const {
143 if (first < 0) {
144 first += m_nComps;
145 }
146 if (last <= 0) {
147 last += m_nComps;
148 }
149 if (isOutOfRange(first) || isOutOfRange(last, true) || first >= last) {
150 return Name();
151 }
152
153 auto it = begin();
154 std::advance(it, first);
155 auto firstComp = *it;
156 std::advance(it, last - first - 1);
157 auto lastComp = *it; // inclusive last component
158 return Name(firstComp.tlv(), lastComp.tlv() + lastComp.size() - firstComp.tlv(), last - first);
159 }
160
165 Name getPrefix(int n = 0) const {
166 return slice(0, n);
167 }
168
182 template<typename... C>
183 Name append(Region& region, const C&... comps) const {
184 Encoder encoder(region);
185 size_t nComps = prependComps(encoder, comps...);
186 uint8_t* room = encoder.prependRoom(m_length);
187 if (room != nullptr) {
188 std::copy_n(m_value, m_length, room);
189 }
190 if (!encoder) {
191 encoder.discard();
192 return Name();
193 }
194 encoder.trim();
195 return Name(encoder.begin(), encoder.size(), m_nComps + nComps);
196 }
197
203 Name clone(Region& region) const {
204 return append(region);
205 }
206
215
217 CompareResult compare(const Name& other) const {
218 size_t commonLength = std::min(m_length, other.m_length);
219 if (commonLength > 0) {
220 int commonCmp = std::memcmp(m_value, other.m_value, commonLength);
221 if (commonCmp < 0) {
222 return CMP_LT;
223 }
224 if (commonCmp > 0) {
225 return CMP_GT;
226 }
227 }
228
229 if (m_length > commonLength) {
230 return CMP_RPREFIX;
231 }
232 if (other.m_length > commonLength) {
233 return CMP_LPREFIX;
234 }
235 return CMP_EQUAL;
236 }
237
239 bool isPrefixOf(const Name& other) const {
240 auto cmp = compare(other);
241 return cmp == CMP_LPREFIX || cmp == CMP_EQUAL;
242 }
243
244 void encodeTo(Encoder& encoder) const {
245 encoder.prependTlv(TT::Name, tlv::Value(m_value, m_length));
246 }
247
248 bool decodeFrom(const Decoder::Tlv& d) {
249 return decodeValue(d.value, d.length);
250 }
251
252#ifdef NDNPH_PRINT_ARDUINO
254 size_t printTo(::Print& p) const final {
255 size_t count = 0;
256 if (m_nComps == 0) {
257 count += p.print('/');
258 } else {
259 for (const auto& comp : *this) {
260 count += p.print('/');
261 // count += p.print(comp);
262 count += comp.printTo(p);
263 }
264 }
265 return count;
266 }
267#endif
268
269private:
270 explicit Name(const uint8_t* value, size_t length, size_t nComps)
271 : m_value(value)
272 , m_length(length)
273 , m_nComps(nComps) {}
274
275 bool decodeValue(const uint8_t* value, size_t length) {
276 m_value = value;
277 if (decodeComps(length)) {
278 return true;
279 }
280 m_value = nullptr;
281 m_length = m_nComps = 0;
282 return false;
283 }
284
285 bool decodeComps(size_t length) {
286 Decoder decoder(m_value, length);
287 auto it = decoder.begin(), end = decoder.end();
288 for (; it != end; ++it) {
289 Component comp;
290 if (!it->decode(comp)) {
291 return false;
292 }
293 m_length += it->size;
294 ++m_nComps;
295 }
296 return !it.hasError();
297 }
298
299 bool isOutOfRange(int i, bool acceptPastEnd = false) const {
300 return i < 0 ||
301 (acceptPastEnd ? i > static_cast<int>(m_nComps) : i >= static_cast<int>(m_nComps));
302 }
303
304 static ssize_t parseUri(uint8_t* buf, size_t bufLen, const char* uri, size_t uriLen,
305 size_t& nComps) {
306 nComps = 0;
307 if (uriLen <= 1) { // empty Name
308 return 0;
309 }
310 const char* uriEnd = uri + uriLen;
311 size_t length = 0;
312 while (uri < uriEnd) {
313 ++uri; // skip '/'
314 const char* compEnd = std::strchr(uri, '/');
315 if (compEnd == nullptr) {
316 compEnd = uriEnd;
317 }
318
319 auto comp = Component::parse(buf + length, bufLen - length, uri, compEnd - uri);
320 if (!comp) {
321 return -1;
322 }
323 ++nComps;
324 length += comp.size();
325 uri = compEnd;
326 }
327 return length;
328 }
329
330 template<typename... C>
331 static size_t prependComps(Encoder& encoder, const Component& comp, const C&... rest) {
332 size_t nComps = prependComps(encoder, rest...);
333 encoder.prepend(comp);
334 return 1 + nComps;
335 }
336
337 template<typename Convention, typename Arg, typename... C>
338 static typename std::enable_if<!std::is_base_of<Component, Convention>::value, size_t>::type
339 prependComps(Encoder& encoder, const Convention&, const Arg& arg, const C&... rest) {
340 size_t nComps = prependComps(encoder, rest...);
341
342 size_t headroom = encoder.availableHeadroom();
343 Region overlay(const_cast<uint8_t*>(encoder.begin() - headroom), headroom);
344 auto comp = Convention::create(overlay, arg);
345
346 uint8_t* room = encoder.prependRoom(comp.size());
347 if (!comp || room == nullptr) {
348 encoder.setError();
349 return 0;
350 }
351 std::memmove(room, comp.tlv(), comp.size());
352 return 1 + nComps;
353 }
354
355 static size_t prependComps(Encoder&) {
356 return 0;
357 }
358
359private:
360 const uint8_t* m_value = nullptr;
361 size_t m_length = 0;
362 size_t m_nComps = 0;
363};
364
365inline bool
366operator==(const Name& lhs, const Name& rhs) {
367 return lhs.compare(rhs) == Name::CMP_EQUAL;
368}
369
370inline bool
371operator<(const Name& lhs, const Name& rhs) {
372 auto cmp = lhs.compare(rhs);
373 return cmp == Name::CMP_LT || cmp == Name::CMP_LPREFIX;
374}
375
376NDNPH_DECLARE_NE(Name, inline)
377NDNPH_DECLARE_GT_LE_GE(Name, inline)
378
379#ifdef NDNPH_PRINT_OSTREAM
381inline std::ostream&
382operator<<(std::ostream& os, const Name& name) {
383 if (name.size() == 0) {
384 return os << '/';
385 }
386 for (const auto& comp : name) {
387 os << '/' << comp;
388 }
389 return os;
390}
391#endif
392
393} // namespace ndnph
394
395#endif // NDNPH_PACKET_NAME_HPP
Name component.
Definition component.hpp:16
static Component parse(Region &region, const char *uri)
Parse from URI.
Definition component.hpp:97
bool decodeFrom(const Decoder::Tlv &d)
Definition component.hpp:169
Iterator over TLV elements.
Definition decoder.hpp:69
Decoded TLV.
Definition decoder.hpp:13
size_t length
Definition decoder.hpp:39
const uint8_t * value
Definition decoder.hpp:40
TLV decoder.
Definition decoder.hpp:10
TLV encoder that accepts items in reverse order.
Definition encoder.hpp:10
void trim() const
Release unused space to the Region.
Definition encoder.hpp:58
uint8_t * prependRoom(size_t size)
Make room to prepend an object.
Definition encoder.hpp:90
void discard()
Release all space to the Region.
Definition encoder.hpp:72
const uint8_t * begin() const
Get output begin.
Definition encoder.hpp:34
bool prependTlv(uint32_t type, OmitEmptyTag omitEmpty, const Arg &... arg)
Prepend TLV, measuring TLV-LENGTH automatically.
Definition encoder.hpp:143
size_t size() const
Get output size.
Definition encoder.hpp:44
Iterator over name components.
Definition name.hpp:91
reference operator*()
Definition name.hpp:105
const Component value_type
Definition name.hpp:95
Iterator(const super &inner)
Definition name.hpp:102
std::ptrdiff_t difference_type
Definition name.hpp:96
std::input_iterator_tag iterator_category
Definition name.hpp:94
pointer operator->()
Definition name.hpp:111
detail::InputIteratorPointerProxy< value_type > pointer
Definition name.hpp:97
Name.
Definition name.hpp:14
static Name parse(Region &region, const char *uri)
Parse from URI.
Definition name.hpp:49
Name(Region &region, std::initializer_list< uint8_t > value)
Construct from TLV-VALUE.
Definition name.hpp:37
size_t length() const
Definition name.hpp:77
Iterator end() const
Definition name.hpp:120
Component operator[](int i) const
Access i-th component.
Definition name.hpp:125
size_t size() const
Get number of components.
Definition name.hpp:86
CompareResult
Name compare result.
Definition name.hpp:208
@ CMP_EQUAL
lhs and rhs are equal
Definition name.hpp:211
@ CMP_RPREFIX
rhs is a prefix of lhs
Definition name.hpp:212
@ CMP_LT
lhs is less than, but not a prefix of rhs
Definition name.hpp:209
@ CMP_GT
rhs is less than, but not a prefix of lhs
Definition name.hpp:213
@ CMP_LPREFIX
lhs is a prefix of rhs
Definition name.hpp:210
bool decodeFrom(const Decoder::Tlv &d)
Definition name.hpp:248
const uint8_t * value() const
Definition name.hpp:81
Name append(Region &region, const C &... comps) const
Append a sequence of components.
Definition name.hpp:183
Name clone(Region &region) const
Clone TLV-VALUE into given region.
Definition name.hpp:203
Name getPrefix(int n=0) const
Get prefix of n components.
Definition name.hpp:165
Name slice(int first=0, int last=0) const
Get sub name [first, last).
Definition name.hpp:142
Name(const uint8_t *value=nullptr, size_t length=0)
Construct referencing TLV-VALUE.
Definition name.hpp:17
Name(Region &region, It first, It last)
Construct from TLV-VALUE.
Definition name.hpp:23
size_t printTo(::Print &p) const final
Print name as URI.
Definition name.hpp:254
Iterator begin() const
Definition name.hpp:116
void encodeTo(Encoder &encoder) const
Definition name.hpp:244
bool isPrefixOf(const Name &other) const
Determine if this name is a prefix of other.
Definition name.hpp:239
CompareResult compare(const Name &other) const
Compare with other name.
Definition name.hpp:217
Definition printing.hpp:22
Region-based memory allocator thats owns memory of NDNph objects.
Definition region.hpp:9
uint8_t * alloc(size_t size)
Allocate a buffer with no alignment requirement.
Definition region.hpp:27
bool free(const uint8_t *first, const uint8_t *last)
Deallocate (part of) last allocated buffer.
Definition region.hpp:51
Wrap a value to appear as InputIterator::pointer.
Definition input-iterator-pointer-proxy.hpp:9
A sequence of bytes, usually TLV-VALUE.
Definition value.hpp:11
@ Name
Definition an.hpp:19
Definition fs.hpp:33
bool operator<(const Name &lhs, const Name &rhs)
Definition name.hpp:371
bool operator==(const ValidityPeriod &lhs, const ValidityPeriod &rhs)
Definition validity-period.hpp:156
#define NDNPH_DECLARE_GT_LE_GE(T, specifier)
Declare operator>, operator<=, operator>= in terms of operator<.
Definition operators.hpp:11
#define NDNPH_DECLARE_NE(T, specifier)
Declare operator!= in terms of operator==.
Definition operators.hpp:7