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 
7 namespace ndnph {
8 
14 class Name : public Printable {
15 public:
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 
209  CMP_LT = -2,
210  CMP_LPREFIX = -1,
211  CMP_EQUAL = 0,
212  CMP_RPREFIX = +1,
213  CMP_GT = +2,
214  };
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 
269 private:
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 
359 private:
360  const uint8_t* m_value = nullptr;
361  size_t m_length = 0;
362  size_t m_nComps = 0;
363 };
364 
365 inline bool
366 operator==(const Name& lhs, const Name& rhs) {
367  return lhs.compare(rhs) == Name::CMP_EQUAL;
368 }
369 
370 inline bool
371 operator<(const Name& lhs, const Name& rhs) {
372  auto cmp = lhs.compare(rhs);
373  return cmp == Name::CMP_LT || cmp == Name::CMP_LPREFIX;
374 }
375 
376 NDNPH_DECLARE_NE(Name, inline)
378 
379 #ifdef NDNPH_PRINT_OSTREAM
381 inline std::ostream&
382 operator<<(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
const uint8_t * begin() const
Get output begin.
Definition: encoder.hpp:34
void trim() const
Release unused space to the Region.
Definition: encoder.hpp:58
void discard()
Release all space to the Region.
Definition: encoder.hpp:72
uint8_t * prependRoom(size_t size)
Make room to prepend an object.
Definition: encoder.hpp:90
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
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
const uint8_t * value() const
Definition: name.hpp:81
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