blob: a255e629b63d8a3e93748514f5658d9e817da49e [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 *
5 * BSD license, See the LICENSE file for more information
6 *
7 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
8 */
9
10#ifndef NDN_TLV_HPP
11#define NDN_TLV_HPP
12
Alexander Afanasyev54467af2014-01-06 15:45:32 -080013#include <stdexcept>
Yingdi Yu27158392014-01-20 13:04:20 -080014#include <iterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015#include "buffer.hpp"
Alexander Afanasyev200dd6f2014-01-28 19:04:25 -080016#include "endian.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080017
18namespace ndn {
19
20/**
21 * @brief Namespace defining NDN-TLV related constants and procedures
22 */
23namespace Tlv {
24
Alexander Afanasyeva465e972014-03-22 17:21:49 -070025class Error : public std::runtime_error
26{
27public:
28 explicit
29 Error(const std::string& what)
30 : std::runtime_error(what)
31 {
32 }
33};
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080034
35enum {
Alexander Afanasyev4b456282014-02-13 00:34:34 -080036 Interest = 5,
37 Data = 6,
38 Name = 7,
39 NameComponent = 8,
40 Selectors = 9,
41 Nonce = 10,
Alexander Afanasyeva465e972014-03-22 17:21:49 -070042 Scope = 11, // deprecated
Alexander Afanasyev4b456282014-02-13 00:34:34 -080043 InterestLifetime = 12,
44 MinSuffixComponents = 13,
45 MaxSuffixComponents = 14,
46 PublisherPublicKeyLocator = 15,
47 Exclude = 16,
48 ChildSelector = 17,
49 MustBeFresh = 18,
50 Any = 19,
51 MetaInfo = 20,
52 Content = 21,
53 SignatureInfo = 22,
54 SignatureValue = 23,
55 ContentType = 24,
56 FreshnessPeriod = 25,
57 FinalBlockId = 26,
58 SignatureType = 27,
59 KeyLocator = 28,
60 KeyLocatorDigest = 29,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080061
62 AppPrivateBlock1 = 128,
63 AppPrivateBlock2 = 32767
64};
65
66enum SignatureType {
67 DigestSha256 = 0,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070068 SignatureSha256WithRsa = 1
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080069};
70
71enum ConentType {
72 ContentType_Default = 0,
73 ContentType_Link = 1,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070074 ContentType_Key = 2
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080075};
76
77/**
78 * @brief Read VAR-NUMBER in NDN-TLV encoding
79 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -070080 * @param [in] begin Begin (pointer or iterator) of the buffer
81 * @param [in] end End (pointer or iterator) of the buffer
82 * @param [out] number Read number
83 *
84 * @throws This call never throws exception
85 *
86 * @return true if number successfully read from input, false otherwise
87 */
88template<class InputIterator>
89inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -070090readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070091
92/**
93 * @brief Read TLV Type
94 *
95 * @param [in] begin Begin (pointer or iterator) of the buffer
96 * @param [in] end End (pointer or iterator) of the buffer
97 * @param [out] number Read type number
98 *
99 * @throws This call never throws exception
100 *
101 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
102 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
103 */
104template<class InputIterator>
105inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700106readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700107
108
109/**
110 * @brief Read VAR-NUMBER in NDN-TLV encoding
111 *
112 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800113 *
114 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
115 */
116template<class InputIterator>
117inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700118readVarNumber(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800119
120/**
121 * @brief Read TLV Type
122 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700123 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
124 *
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800125 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
126 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
127 */
128template<class InputIterator>
129inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700130readType(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800131
132/**
133 * @brief Get number of bytes necessary to hold value of VAR-NUMBER
134 */
135inline size_t
136sizeOfVarNumber(uint64_t varNumber);
137
138/**
139 * @brief Write VAR-NUMBER to the specified stream
140 */
141inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700142writeVarNumber(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800143
144/**
145 * @brief Read nonNegativeInteger in NDN-TLV encoding
146 *
147 * This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
148 *
149 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
150 *
151 * How many bytes will be read is directly controlled by the size parameter, which can be either
152 * 1, 2, 4, or 8. If the value of size is different, then an exception will be thrown.
153 */
154template<class InputIterator>
155inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700156readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800157
158/**
159 * @brief Get number of bytes necessary to hold value of nonNegativeInteger
160 */
161inline size_t
162sizeOfNonNegativeInteger(uint64_t varNumber);
163
164/**
165 * @brief Write nonNegativeInteger to the specified stream
166 */
167inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700168writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800169
170/////////////////////////////////////////////////////////////////////////////////
171/////////////////////////////////////////////////////////////////////////////////
172/////////////////////////////////////////////////////////////////////////////////
173
174// Inline implementations
175
176/////////////////////////////////////////////////////////////////////////////////
177/////////////////////////////////////////////////////////////////////////////////
178/////////////////////////////////////////////////////////////////////////////////
179
180template<class InputIterator>
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700181inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700182readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700183{
184 if (begin == end)
185 return false;
186
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700187 uint8_t firstOctet = *begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700188 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700189 if (firstOctet < 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700190 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700191 number = firstOctet;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700192 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700193 else if (firstOctet == 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700194 {
195 if (end - begin < 2)
196 return false;
197
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700198 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700199 begin += 2;
200 number = be16toh(value);
201 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700202 else if (firstOctet == 254)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700203 {
204 if (end - begin < 4)
205 return false;
206
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700207 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700208 begin += 4;
209 number = be32toh(value);
210 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700211 else // if (firstOctet == 255)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700212 {
213 if (end - begin < 8)
214 return false;
215
216 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
217 begin += 8;
218
219 number = be64toh(value);
220 }
221
222 return true;
223}
224
225template<class InputIterator>
226inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700227readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700228{
Mickey Sweatt632e0572014-04-20 00:36:32 -0700229 uint64_t number = 0;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700230 bool isOk = readVarNumber(begin, end, number);
231 if (!isOk || number > std::numeric_limits<uint32_t>::max())
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700232 {
233 return false;
234 }
235
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700236 type = static_cast<uint64_t>(number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700237 return true;
238}
239
240template<class InputIterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800241inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700242readVarNumber(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800243{
244 if (begin == end)
245 throw Error("Empty buffer during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700246
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700247 uint64_t value;
248 bool isOk = readVarNumber(begin, end, value);
249 if (!isOk)
250 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700251
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700252 return value;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800253}
254
Yingdi Yu27158392014-01-20 13:04:20 -0800255template<>
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700256inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700257readVarNumber<std::istream_iterator<uint8_t> >(std::istream_iterator<uint8_t>& begin,
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700258 const std::istream_iterator<uint8_t>& end,
259 uint64_t& value)
Yingdi Yu27158392014-01-20 13:04:20 -0800260{
261 if (begin == end)
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700262 return false;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700263
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700264 uint8_t firstOctet = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800265 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700266 if (firstOctet < 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800267 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700268 value = firstOctet;
Yingdi Yu27158392014-01-20 13:04:20 -0800269 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700270 else if (firstOctet == 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800271 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700272 value = 0;
273 size_t count = 0;
274 for (; begin != end && count < 2; ++count)
275 {
276 value = ((value << 8) | *begin);
277 begin++;
278 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700279
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700280 if (count != 2)
281 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800282 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700283 else if (firstOctet == 254)
Yingdi Yu27158392014-01-20 13:04:20 -0800284 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700285 value = 0;
286 size_t count = 0;
287 for (; begin != end && count < 4; ++count)
288 {
289 value = ((value << 8) | *begin);
290 begin++;
291 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700292
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700293 if (count != 4)
294 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800295 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700296 else // if (firstOctet == 255)
Yingdi Yu27158392014-01-20 13:04:20 -0800297 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700298 value = 0;
299 size_t count = 0;
300 for (; begin != end && count < 8; ++count)
301 {
302 value = ((value << 8) | *begin);
303 begin++;
304 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700305
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700306 if (count != 8)
307 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800308 }
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700309
310 return true;
Yingdi Yu27158392014-01-20 13:04:20 -0800311}
312
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800313template<class InputIterator>
314inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700315readType(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800316{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700317 uint64_t type = readVarNumber(begin, end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800318 if (type > std::numeric_limits<uint32_t>::max())
319 {
320 throw Error("TLV type code exceeds allowed maximum");
321 }
322
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700323 return static_cast<uint32_t>(type);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800324}
325
326size_t
327sizeOfVarNumber(uint64_t varNumber)
328{
329 if (varNumber < 253) {
330 return 1;
331 }
332 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
333 return 3;
334 }
335 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
336 return 5;
337 }
338 else {
339 return 9;
340 }
341}
342
343inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700344writeVarNumber(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800345{
346 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200347 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800348 return 1;
349 }
350 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200351 os.put(static_cast<char>(253));
352 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700353 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800354 return 3;
355 }
356 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200357 os.put(static_cast<char>(254));
358 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700359 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800360 return 5;
361 }
362 else {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200363 os.put(static_cast<char>(255));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800364 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700365 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800366 return 9;
367 }
368}
369
370template<class InputIterator>
371inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700372readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800373{
374 switch (size) {
375 case 1:
376 {
377 if (end - begin < 1)
378 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700379
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800380 uint8_t value = *begin;
381 begin++;
382 return value;
383 }
384 case 2:
385 {
386 if (end - begin < 2)
387 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700388
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700389 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800390 begin += 2;
391 return be16toh(value);
392 }
393 case 4:
394 {
395 if (end - begin < 4)
396 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700397
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700398 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800399 begin += 4;
400 return be32toh(value);
401 }
402 case 8:
403 {
404 if (end - begin < 8)
405 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700406
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800407 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
408 begin += 8;
409 return be64toh(value);
410 }
411 }
412 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
413}
414
Yingdi Yu27158392014-01-20 13:04:20 -0800415template<>
416inline uint64_t
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700417readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700418 std::istream_iterator<uint8_t>& begin,
419 const std::istream_iterator<uint8_t>& end)
Yingdi Yu27158392014-01-20 13:04:20 -0800420{
421 switch (size) {
422 case 1:
423 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700424 if (begin == end)
Yingdi Yu27158392014-01-20 13:04:20 -0800425 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700426
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700427 uint64_t value = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800428 begin++;
429 return value;
430 }
431 case 2:
432 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700433 uint64_t value = 0;
434 size_t count = 0;
435 for (; begin != end && count < 2; ++count)
436 {
437 value = ((value << 8) | *begin);
438 begin++;
439 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700440
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700441 if (count != 2)
Yingdi Yu27158392014-01-20 13:04:20 -0800442 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700443
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700444 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800445 }
446 case 4:
447 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700448 uint64_t value = 0;
449 size_t count = 0;
450 for (; begin != end && count < 4; ++count)
451 {
452 value = ((value << 8) | *begin);
453 begin++;
454 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700455
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700456 if (count != 4)
Yingdi Yu27158392014-01-20 13:04:20 -0800457 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700458
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700459 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800460 }
461 case 8:
462 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700463 uint64_t value = 0;
464 size_t count = 0;
465 for (; begin != end && count < 8; ++count)
466 {
467 value = ((value << 8) | *begin);
468 begin++;
469 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700470
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700471 if (count != 8)
Yingdi Yu27158392014-01-20 13:04:20 -0800472 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700473
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700474 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800475 }
476 }
477 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
478}
479
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800480inline size_t
481sizeOfNonNegativeInteger(uint64_t varNumber)
482{
483 if (varNumber < 253) {
484 return 1;
485 }
486 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
487 return 2;
488 }
489 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
490 return 4;
491 }
492 else {
493 return 8;
494 }
495}
496
497
498inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700499writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800500{
501 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200502 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800503 return 1;
504 }
505 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200506 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700507 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800508 return 2;
509 }
510 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200511 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700512 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800513 return 4;
514 }
515 else {
516 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700517 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800518 return 8;
519 }
520}
521
522
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700523} // namespace Tlv
524
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800525} // namespace ndn
526
527#endif // NDN_TLV_HPP