NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
name-component.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2018 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  *
21  * @author Jeff Thompson <jefft0@remap.ucla.edu>
22  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
23  * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
24  */
25 
28 
29 #include <cstdlib>
30 #include <cstring>
31 #include <sstream>
32 
33 namespace ndn {
34 namespace name {
35 
36 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Component>));
37 BOOST_CONCEPT_ASSERT((WireEncodable<Component>));
39 BOOST_CONCEPT_ASSERT((WireDecodable<Component>));
40 static_assert(std::is_base_of<tlv::Error, Component::Error>::value,
41  "name::Component::Error must inherit from tlv::Error");
42 
43 void
44 Component::ensureValid() const
45 {
47  BOOST_THROW_EXCEPTION(Error("TLV-TYPE " + to_string(type()) + " is not a valid NameComponent"));
48  }
50 }
51 
52 Component::Component(uint32_t type)
53  : Block(type)
54 {
55  ensureValid();
56 }
57 
59  : Block(wire)
60 {
61  ensureValid();
62 }
63 
64 Component::Component(uint32_t type, ConstBufferPtr buffer)
65  : Block(type, std::move(buffer))
66 {
67  ensureValid();
68 }
69 
70 Component::Component(uint32_t type, const uint8_t* value, size_t valueLen)
71  : Block(makeBinaryBlock(type, value, valueLen))
72 {
73  ensureValid();
74 }
75 
76 Component::Component(const char* str)
77  : Block(makeBinaryBlock(tlv::GenericNameComponent, str, std::char_traits<char>::length(str)))
78 {
79 }
80 
81 Component::Component(const std::string& str)
83 {
84 }
85 
86 static Component
87 parseUriEscapedValue(uint32_t type, const char* input, size_t len)
88 {
89  std::ostringstream oss;
90  unescape(oss, input, len);
91  std::string value = oss.str();
92  if (value.find_first_not_of('.') == std::string::npos) { // all periods
93  if (value.size() < 3) {
94  BOOST_THROW_EXCEPTION(Component::Error("Illegal URI (name component cannot be . or ..)"));
95  }
96  return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size() - 3);
97  }
98  return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size());
99 }
100 
101 Component
102 Component::fromEscapedString(const std::string& input)
103 {
104  size_t equalPos = input.find('=');
105  if (equalPos == std::string::npos) {
106  return parseUriEscapedValue(tlv::GenericNameComponent, input.data(), input.size());
107  }
108 
109  long type = std::strtol(input.data(), nullptr, 10);
111  to_string(type).size() == equalPos) {
112  size_t valuePos = equalPos + 1;
113  return parseUriEscapedValue(static_cast<uint32_t>(type), input.data() + valuePos,
114  input.size() - valuePos);
115  }
116 
117  auto typePrefix = input.substr(0, equalPos);
118  auto ct = detail::getComponentTypeTable().findByUriPrefix(typePrefix);
119  if (ct == nullptr) {
120  BOOST_THROW_EXCEPTION(Error("Incorrect TLV-TYPE '" + typePrefix + "' in NameComponent URI"));
121  }
122  return ct->parseAltUriValue(input.substr(equalPos + 1));
123 }
124 
125 void
126 Component::toUri(std::ostream& os) const
127 {
129 }
130 
131 std::string
133 {
134  std::ostringstream os;
135  toUri(os);
136  return os.str();
137 }
138 
140 
141 bool
143 {
144  return (value_size() == 1 || value_size() == 2 ||
145  value_size() == 4 || value_size() == 8);
146 }
147 
148 bool
149 Component::isNumberWithMarker(uint8_t marker) const
150 {
151  return (!empty() && value()[0] == marker &&
152  (value_size() == 2 || value_size() == 3 ||
153  value_size() == 5 || value_size() == 9));
154 }
155 
156 bool
158 {
160 }
161 
162 bool
164 {
166 }
167 
168 bool
170 {
172 }
173 
174 bool
176 {
178 }
179 
180 bool
182 {
184 }
185 
187 
188 uint64_t
190 {
191  if (!isNumber())
192  BOOST_THROW_EXCEPTION(Error("Name component does not have nonNegativeInteger value"));
193 
194  return readNonNegativeInteger(*this);
195 }
196 
197 uint64_t
198 Component::toNumberWithMarker(uint8_t marker) const
199 {
200  if (!isNumberWithMarker(marker))
201  BOOST_THROW_EXCEPTION(Error("Name component does not have the requested marker "
202  "or the value is not a nonNegativeInteger"));
203 
204  Buffer::const_iterator valueBegin = value_begin() + 1;
205  return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
206 }
207 
208 uint64_t
210 {
212 }
213 
214 uint64_t
216 {
218 }
219 
220 uint64_t
222 {
224 }
225 
228 {
230  return time::getUnixEpoch() + time::microseconds(value);
231 }
232 
233 uint64_t
235 {
237 }
238 
240 
241 Component
242 Component::fromNumber(uint64_t number)
243 {
245 }
246 
247 Component
248 Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
249 {
250  EncodingEstimator estimator;
251 
252  size_t valueLength = estimator.prependNonNegativeInteger(number);
253  valueLength += estimator.prependByteArray(&marker, 1);
254  size_t totalLength = valueLength;
255  totalLength += estimator.prependVarNumber(valueLength);
256  totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
257 
258  EncodingBuffer encoder(totalLength, 0);
259  encoder.prependNonNegativeInteger(number);
260  encoder.prependByteArray(&marker, 1);
261  encoder.prependVarNumber(valueLength);
262  encoder.prependVarNumber(tlv::GenericNameComponent);
263 
264  return encoder.block();
265 }
266 
267 Component
268 Component::fromVersion(uint64_t version)
269 {
270  return fromNumberWithMarker(VERSION_MARKER, version);
271 }
272 
273 Component
274 Component::fromSegment(uint64_t segmentNo)
275 {
276  return fromNumberWithMarker(SEGMENT_MARKER, segmentNo);
277 }
278 
279 Component
281 {
283 }
284 
285 Component
287 {
288  using namespace time;
289  uint64_t value = duration_cast<microseconds>(timePoint - getUnixEpoch()).count();
291 }
292 
293 Component
295 {
297 }
298 
300 
301 bool
303 {
304  return type() == tlv::GenericNameComponent;
305 }
306 
307 bool
309 {
310  return detail::getComponentType1().match(*this);
311 }
312 
313 Component
315 {
316  return detail::getComponentType1().create(digest);
317 }
318 
319 Component
320 Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
321 {
322  return detail::getComponentType1().create(digest, digestSize);
323 }
324 
325 bool
327 {
328  return detail::getComponentType2().match(*this);
329 }
330 
331 Component
333 {
334  return detail::getComponentType2().create(digest);
335 }
336 
337 Component
338 Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
339 {
340  return detail::getComponentType2().create(digest, digestSize);
341 }
342 
344 
345 bool
346 Component::equals(const Component& other) const
347 {
348  return type() == other.type() &&
349  value_size() == other.value_size() &&
350  (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
351  std::equal(value_begin(), value_end(), other.value_begin()));
352 }
353 
354 int
355 Component::compare(const Component& other) const
356 {
357  if (this->hasWire() && other.hasWire()) {
358  // In the common case where both components have wire encoding,
359  // it's more efficient to simply compare the wire encoding.
360  // This works because lexical order of TLV encoding happens to be
361  // the same as canonical order of the value.
362  return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
363  }
364 
365  int cmpType = type() - other.type();
366  if (cmpType != 0)
367  return cmpType;
368 
369  int cmpSize = value_size() - other.value_size();
370  if (cmpSize != 0)
371  return cmpSize;
372 
373  if (empty())
374  return 0;
375 
376  return std::memcmp(value(), other.value(), value_size());
377 }
378 
379 Component
381 {
382  bool isOverflow = false;
383  Component successor;
384  std::tie(isOverflow, successor) =
386  if (!isOverflow) {
387  return successor;
388  }
389 
390  uint32_t type = this->type() + 1;
391  const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
392  return Component(type, value.data(), value.size());
393 }
394 
395 template<encoding::Tag TAG>
396 size_t
398 {
399  size_t totalLength = 0;
400  if (value_size() > 0)
401  totalLength += encoder.prependByteArray(value(), value_size());
402  totalLength += encoder.prependVarNumber(value_size());
403  totalLength += encoder.prependVarNumber(type());
404  return totalLength;
405 }
406 
408 
409 const Block&
411 {
412  if (this->hasWire())
413  return *this;
414 
415  EncodingEstimator estimator;
416  size_t estimatedSize = wireEncode(estimator);
417 
418  EncodingBuffer buffer(estimatedSize, 0);
419  wireEncode(buffer);
420 
421  const_cast<Component&>(*this) = buffer.block();
422  return *this;
423 }
424 
425 void
427 {
428  *this = wire;
429  // validity check is done within Component(const Block& wire)
430 }
431 
432 } // namespace name
433 } // namespace ndn
static Component fromParametersSha256Digest(ConstBufferPtr digest)
Create ParametersSha256DigestComponent component.
static Component fromNumber(uint64_t number)
Create a component encoded as nonNegativeInteger.
static Component fromSequenceNumber(uint64_t seqNo)
Create sequence number component using NDN naming conventions.
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:249
Copyright (c) 2011-2015 Regents of the University of California.
const ComponentTypeTable & getComponentTypeTable()
Get the global ComponentTypeTable.
const ComponentType & get(uint32_t type) const
Retrieve ComponentType by TLV-TYPE.
std::string toUri() const
Convert *this by escaping characters according to the NDN URI Scheme.
bool isSequenceNumber() const
Check if the component is sequence number per NDN naming conventions.
uint64_t toSequenceNumber() const
Interpret as sequence number component using NDN naming conventions.
static Component fromNumberWithMarker(uint8_t marker, uint64_t number)
Create a component encoded as NameComponentWithMarker.
size_t value_size() const
Get size of TLV-VALUE aka TLV-LENGTH.
Definition: block.cpp:316
Component(uint32_t type=tlv::GenericNameComponent)
Construct a NameComponent of TLV-TYPE type, using empty TLV-VALUE.
bool isNumberWithMarker(uint8_t marker) const
Check if the component is NameComponentWithMarker per NDN naming conventions.
static Component fromTimestamp(const time::system_clock::TimePoint &timePoint)
Create sequence number component using NDN naming conventions.
bool match(const Component &comp) const
const uint8_t * wire() const
Get pointer to encoded wire.
Definition: block.cpp:289
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, Iterator end)
Read nonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:484
int compare(const Component &other) const
Compare this to the other Component using NDN canonical ordering.
const uint8_t * value() const
Get pointer to TLV-VALUE.
Definition: block.cpp:310
virtual void writeUri(std::ostream &os, const Component &comp) const
Write URI representation of comp to os.
Block makeNonNegativeIntegerBlock(uint32_t type, uint64_t value)
Create a TLV block containing a non-negative integer.
const Sha256ComponentType & getComponentType1()
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
static Component fromSegmentOffset(uint64_t offset)
Create segment offset component using NDN naming conventions.
const Sha256ComponentType & getComponentType2()
static const uint8_t SEGMENT_OFFSET_MARKER
Segment offset marker for NDN naming conventions.
bool isNumber() const
Check if the component is nonNegativeInteger.
Buffer::const_iterator value_begin() const
Get begin iterator of TLV-VALUE.
Definition: block.hpp:269
bool isSegmentOffset() const
Check if the component is segment offset per NDN naming conventions.
bool isParametersSha256Digest() const
Check if the component is ParametersSha256DigestComponent.
static Component fromSegment(uint64_t segmentNo)
Create segment number component using NDN naming conventions.
Component getSuccessor() const
Get the successor of this name component.
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:60
size_t size() const
Get size of encoded wire, including Type-Length-Value.
Definition: block.cpp:298
virtual std::pair< bool, Component > getSuccessor(const Component &comp) const
Calculate the successor of comp.
Component create(ConstBufferPtr value) const
element_const_iterator find(uint32_t type) const
Find the first sub element of specified TLV-TYPE.
Definition: block.cpp:434
static Component fromEscapedString(const char *input, size_t beginOffset, size_t endOffset)
Decode NameComponent from a URI component.
Block makeBinaryBlock(uint32_t type, const uint8_t *value, size_t length)
Create a TLV block copying TLV-VALUE from raw buffer.
bool isSegment() const
Check if the component is segment number per NDN naming conventions.
Block makeStringBlock(uint32_t type, const std::string &value)
Create a TLV block containing a string.
Buffer::const_iterator value_end() const
Get end iterator of TLV-VALUE.
Definition: block.hpp:278
uint64_t toSegmentOffset() const
Interpret as segment offset component using NDN naming conventions.
virtual const std::vector< uint8_t > & getMinValue() const
Return the minimum allowable TLV-VALUE of this component type.
std::string unescape(const std::string &str)
Decode a percent-encoded string.
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
bool equals(const Component &other) const
Check if this is the same component as other.
const Block & wireEncode() const
Encode to a wire format.
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
static const uint8_t VERSION_MARKER
Version marker for NDN naming conventions.
const ComponentType * findByUriPrefix(const std::string &prefix) const
Retrieve ComponentType by alternate URI prefix.
time_point TimePoint
Definition: time.hpp:195
static Component parseUriEscapedValue(uint32_t type, const char *input, size_t len)
Represents a name component.
void wireDecode(const Block &wire)
Decode from the wire format.
uint64_t toVersion() const
Interpret as version component using NDN naming conventions.
uint64_t toSegment() const
Interpret as segment number component using NDN naming conventions.
static const uint8_t SEGMENT_MARKER
Segment marker for NDN naming conventions.
NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component)
bool isTimestamp() const
Check if the component is timestamp per NDN naming conventions.
static Component fromVersion(uint64_t version)
Create version component using NDN naming conventions.
std::string to_string(const V &v)
Definition: backports.hpp:67
static const uint8_t SEQUENCE_NUMBER_MARKER
Sequence number marker for NDN naming conventions.
uint64_t toNumberWithMarker(uint8_t marker) const
Interpret this name component as NameComponentWithMarker.
bool isGeneric() const
Check if the component is GenericComponent.
bool isVersion() const
Check if the component is version per NDN naming conventions.
virtual void check(const Component &comp) const
Throw Component::Error if comp is invalid.
static Component fromImplicitSha256Digest(ConstBufferPtr digest)
Create ImplicitSha256DigestComponent component.
time::system_clock::TimePoint toTimestamp() const
Interpret as timestamp component using NDN naming conventions.
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:44
static const uint8_t TIMESTAMP_MARKER
Timestamp marker for NDN naming conventions.
a concept check for TLV abstraction with .wireDecode method and constructible from Block
Definition: concepts.hpp:80
EncodingImpl< EncoderTag > EncodingBuffer
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:249
const system_clock::TimePoint & getUnixEpoch()
Get system_clock::TimePoint representing UNIX time epoch (00:00:00 on Jan 1, 1970)
Definition: time.cpp:106
size_t prependNonNegativeInteger(uint64_t integer) const noexcept
Prepend non-negative integer integer of NDN TLV encoding.
Definition: estimator.cpp:51
EncodingImpl< EstimatorTag > EncodingEstimator
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:126