All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
name-component.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
10 #ifndef NDN_NAME_COMPONENT_HPP
11 #define NDN_NAME_COMPONENT_HPP
12 
13 #include "common.hpp"
14 #include "encoding/block.hpp"
16 #include "util/string-helper.hpp"
17 
18 namespace ndn {
19 namespace name {
20 
24 class Component : public Block
25 {
26 public:
30  class Error : public Block::Error
31  {
32  public:
33  explicit
34  Error(const std::string& what)
35  : Block::Error(what)
36  {
37  }
38  };
39 
43  Component();
44 
52  Component(const Block& wire);
53 
58  explicit
59  Component(const ConstBufferPtr& buffer);
60 
65  explicit
66  Component(const Buffer& value);
67 
73  Component(const uint8_t* value, size_t valueLen);
74 
75  template<class InputIterator>
76  Component(InputIterator begin, InputIterator end);
77 
78  explicit
79  Component(const char* str);
80 
81  explicit
82  Component(const std::string& str);
83 
87  template<bool T>
88  size_t
89  wireEncode(EncodingImpl<T>& block) const;
90 
94  inline const Block&
95  wireEncode() const;
96 
100  inline void
101  wireDecode(const Block& wire);
102 
112  static Component
113  fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset);
114 
122  static Component
123  fromEscapedString(const char* escapedString)
124  {
125  return fromEscapedString(escapedString, 0, ::strlen(escapedString));
126  }
127 
135  static Component
136  fromEscapedString(const std::string& escapedString)
137  {
138  return fromEscapedString(escapedString.c_str());
139  }
140 
147  void
148  toEscapedString(std::ostream& result) const;
149 
156  inline std::string
158  {
159  std::ostringstream result;
160  toEscapedString(result);
161  return result.str();
162  }
163 
164  inline void
165  toUri(std::ostream& result) const
166  {
167  return toEscapedString(result);
168  }
169 
170  inline std::string
171  toUri() const
172  {
173  return toEscapedString();
174  }
175 
183  uint64_t
184  toNumber() const;
185 
189  uint64_t
190  toVersion() const;
191 
195  uint64_t
196  toSegment() const;
197 
206  static Component
207  fromNumber(uint64_t number);
208 
214  bool
215  equals(const Component& other) const
216  {
217  if (value_size() != other.value_size())
218  return false;
219  if (value_size() == 0 /* == other.value_size()*/)
220  return true;
221 
222  // somehow, behavior is wrong on OSX 10.9 when component is empty
223  // (probably some bug in STL...)
224  return std::equal(value_begin(), value_end(), other.value_begin());
225  }
226 
227  bool
228  empty() const
229  {
230  return !hasValue();
231  }
232 
238  bool
239  operator==(const Component& other) const { return equals(other); }
240 
246  bool
247  operator!=(const Component& other) const { return !equals(other); }
248 
257  int
258  compare(const Component& other) const;
259 
266  bool
267  operator<=(const Component& other) const { return compare(other) <= 0; }
268 
275  bool
276  operator<(const Component& other) const { return compare(other) < 0; }
277 
284  bool
285  operator>=(const Component& other) const { return compare(other) >= 0; }
286 
293  bool
294  operator>(const Component& other) const { return compare(other) > 0; }
295 
296  //
297  // !!! MUST NOT INCLUDE ANY DATA HERE !!!
298  //
299  // This class is just a helper and is directly reinterpret_cast'ed from Block
300 };
301 
302 inline std::ostream&
303 operator << (std::ostream& os, const Component& component)
304 {
305  component.toEscapedString(os);
306  return os;
307 }
308 
309 inline
311  : Block(Tlv::NameComponent)
312 {
313 }
314 
315 inline
317  : Block(wire)
318 {
319  if (type() != Tlv::NameComponent)
320  throw Error("Constructing name component from non name component TLV wire block");
321 }
322 
323 inline
325  : Block (Tlv::NameComponent, buffer)
326 {
327 }
328 
329 inline
331  : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(value)))
332 {
333 }
334 
335 inline
336 Component::Component(const uint8_t* value, size_t valueLen)
337  : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(value, valueLen)))
338 {
339 }
340 
341 template<class InputIterator>
342 inline
343 Component::Component(InputIterator begin, InputIterator end)
344  : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(begin, end)))
345 {
346 }
347 
348 inline
349 Component::Component(const char* str)
350  : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(str, ::strlen(str))))
351 {
352 }
353 
354 inline
355 Component::Component(const std::string& str)
356  : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(str.begin(), str.end())))
357 {
358 }
359 
360 
361 inline Component
362 Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
363 {
364  std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
365  trim(trimmedString);
366  std::string value = unescape(trimmedString);
367 
368  if (value.find_first_not_of(".") == std::string::npos) {
369  // Special case for component of only periods.
370  if (value.size() <= 2)
371  // Zero, one or two periods is illegal. Ignore this component.
372  return Component();
373  else
374  // Remove 3 periods.
375  return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
376  }
377  else
378  return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
379 }
380 
381 
382 inline void
383 Component::toEscapedString(std::ostream& result) const
384 {
385  const uint8_t* valuePtr = value();
386  size_t valueSize = value_size();
387 
388  bool gotNonDot = false;
389  for (unsigned i = 0; i < valueSize; ++i) {
390  if (valuePtr[i] != 0x2e) {
391  gotNonDot = true;
392  break;
393  }
394  }
395  if (!gotNonDot) {
396  // Special case for component of zero or more periods. Add 3 periods.
397  result << "...";
398  for (size_t i = 0; i < valueSize; ++i)
399  result << '.';
400  }
401  else {
402  // In case we need to escape, set to upper case hex and save the previous flags.
403  std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
404 
405  for (size_t i = 0; i < valueSize; ++i) {
406  uint8_t x = valuePtr[i];
407  // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
408  if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
409  (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
410  x == 0x2e || x == 0x5f)
411  result << x;
412  else {
413  result << '%';
414  if (x < 16)
415  result << '0';
416  result << (unsigned int)x;
417  }
418  }
419 
420  // Restore.
421  result.flags(saveFlags);
422  }
423 }
424 
425 
426 inline Component
427 Component::fromNumber(uint64_t number)
428 {
431 }
432 
433 
434 inline uint64_t
436 {
438  return readNonNegativeInteger(static_cast<const Block&>(*this));
439 }
440 
441 
442 inline uint64_t
444 {
445  return toNumber();
446 }
447 
448 inline uint64_t
450 {
451  return toNumber();
452 }
453 
454 inline int
455 Component::compare(const Component& other) const
456 {
457  // Imitate ndn_Exclude_compareComponents.
458  if (value_size() < other.value_size())
459  return -1;
460  if (value_size() > other.value_size())
461  return 1;
462 
463  if (value_size() == 0)
464  return 0;
465 
466  // The components are equal length. Just do a byte compare.
467  return std::memcmp(value(), other.value(), value_size());
468 }
469 
470 
471 template<bool T>
472 inline size_t
474 {
475  size_t totalLength = 0;
476  if (value_size() > 0)
477  totalLength += block.prependByteArray (value(), value_size());
478  totalLength += block.prependVarNumber (value_size());
479  totalLength += block.prependVarNumber (Tlv::NameComponent);
480  return totalLength;
481 }
482 
486 inline const Block&
488 {
489  if (this->hasWire())
490  return *this;
491 
492  EncodingEstimator estimator;
493  size_t estimatedSize = wireEncode(estimator);
494 
495  EncodingBuffer buffer(estimatedSize, 0);
496  wireEncode(buffer);
497 
498  const_cast<Component&>(*this) = buffer.block();
499  return *this;
500 }
501 
505 inline void
507 {
508  if (wire.type() != Tlv::NameComponent)
509  throw Error("wireDecode name component from non name component TLV wire block");
510 
511  *this = wire;
512 }
513 
514 
515 } // namespace name
516 } // namespace ndn
517 
518 #endif // NDN_NAME_COMPONENT_HPP
static Component fromNumber(uint64_t number)
Create a component encoded as nonNegativeInteger.
bool hasValue() const
Check if the Block has value block (no type and length are encoded)
Definition: block.hpp:294
void toEscapedString(std::ostream &result) const
Write the value to result, escaping characters according to the NDN URI Scheme.
Block nonNegativeIntegerBlock(uint32_t type, uint64_t value)
int compare(const Component &other) const
Compare this to the other Component using NDN canonical ordering.
static Component fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
Make a Blob value by decoding the escapedString between beginOffset and endOffset according to the ND...
const Block & wireEncode() const
Encode to a wire format.
std::string toUri() const
Buffer::const_iterator end() const
Definition: block.hpp:406
bool operator==(const Component &other) const
Check if this is the same component as other.
std::ostream & operator<<(std::ostream &os, const Component &component)
Class representing wire element of the NDN packet.
Definition: block.hpp:26
bool operator<(const Component &other) const
Return true if this is less than the other Component in the NDN canonical ordering.
uint64_t readNonNegativeInteger(const Block &block)
Buffer::const_iterator value_begin() const
Definition: block.hpp:425
Buffer::const_iterator value_end() const
Definition: block.hpp:431
ptr_lib::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:17
uint64_t toVersion() const
An alias for toNumber()
static Component fromEscapedString(const char *escapedString)
Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
uint64_t toSegment() const
An alias for toNumber()
static Component fromEscapedString(const std::string &escapedString)
Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
Component()
Create a new Name::Component with a null value.
std::string toEscapedString() const
Convert the value by escaping characters according to the NDN URI Scheme.
bool operator<=(const Component &other) const
Return true if this is less than or equal to the other Component in the NDN canonical ordering...
bool operator!=(const Component &other) const
Check if this is not the same component as other.
std::string unescape(const std::string &str)
Return a copy of str, converting each escaped &quot;%XX&quot; to the char value.
void toUri(std::ostream &result) const
size_t value_size() const
Definition: block.hpp:455
uint32_t type() const
Definition: block.hpp:320
Component holds a read-only name component value.
void wireDecode(const Block &wire)
Decode from the wire format.
const uint8_t * wire() const
Definition: block.hpp:437
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.hpp:288
void trim(std::string &str)
Modify str in place to erase whitespace on the left and right.
const uint8_t * value() const
Definition: block.hpp:446
bool equals(const Component &other) const
Check if this is the same component as other.
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
Class representing a general-use automatically managed/resized buffer.
Definition: buffer.hpp:28
bool operator>=(const Component &other) const
Return true if this is less than or equal to the other Component in the NDN canonical ordering...
Error that can be thrown from Block.
Definition: block.hpp:34
Class representing wire element of the NDN packet.
Buffer::const_iterator begin() const
Definition: block.hpp:397
bool operator>(const Component &other) const
Return true if this is greater than the other Component in the NDN canonical ordering.
Error that can be thrown from name::Component.
Error(const std::string &what)