blob: e56695c5282d41f605716a5dd13c8c86f5f35d6e [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08004 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080020 */
21
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070022#ifndef NDN_ENCODING_TLV_HPP
23#define NDN_ENCODING_TLV_HPP
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080024
Alexander Afanasyev54467af2014-01-06 15:45:32 -080025#include <stdexcept>
Yingdi Yu27158392014-01-20 13:04:20 -080026#include <iterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080027#include "buffer.hpp"
Alexander Afanasyev200dd6f2014-01-28 19:04:25 -080028#include "endian.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080029
30namespace ndn {
31
32/**
33 * @brief Namespace defining NDN-TLV related constants and procedures
34 */
35namespace Tlv {
36
Alexander Afanasyeva465e972014-03-22 17:21:49 -070037class Error : public std::runtime_error
38{
39public:
40 explicit
41 Error(const std::string& what)
42 : std::runtime_error(what)
43 {
44 }
45};
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080046
47enum {
Alexander Afanasyev4b456282014-02-13 00:34:34 -080048 Interest = 5,
49 Data = 6,
50 Name = 7,
51 NameComponent = 8,
52 Selectors = 9,
53 Nonce = 10,
Alexander Afanasyeva465e972014-03-22 17:21:49 -070054 Scope = 11, // deprecated
Alexander Afanasyev4b456282014-02-13 00:34:34 -080055 InterestLifetime = 12,
56 MinSuffixComponents = 13,
57 MaxSuffixComponents = 14,
58 PublisherPublicKeyLocator = 15,
59 Exclude = 16,
60 ChildSelector = 17,
61 MustBeFresh = 18,
62 Any = 19,
63 MetaInfo = 20,
64 Content = 21,
65 SignatureInfo = 22,
66 SignatureValue = 23,
67 ContentType = 24,
68 FreshnessPeriod = 25,
69 FinalBlockId = 26,
70 SignatureType = 27,
71 KeyLocator = 28,
72 KeyLocatorDigest = 29,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073
74 AppPrivateBlock1 = 128,
75 AppPrivateBlock2 = 32767
76};
77
78enum SignatureType {
79 DigestSha256 = 0,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070080 SignatureSha256WithRsa = 1
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080081};
82
83enum ConentType {
84 ContentType_Default = 0,
85 ContentType_Link = 1,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070086 ContentType_Key = 2
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080087};
88
89/**
90 * @brief Read VAR-NUMBER in NDN-TLV encoding
91 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -070092 * @param [in] begin Begin (pointer or iterator) of the buffer
93 * @param [in] end End (pointer or iterator) of the buffer
94 * @param [out] number Read number
95 *
96 * @throws This call never throws exception
97 *
98 * @return true if number successfully read from input, false otherwise
99 */
100template<class InputIterator>
101inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700102readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700103
104/**
105 * @brief Read TLV Type
106 *
107 * @param [in] begin Begin (pointer or iterator) of the buffer
108 * @param [in] end End (pointer or iterator) of the buffer
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700109 * @param [out] type Read type number
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700110 *
111 * @throws This call never throws exception
112 *
113 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
114 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
115 */
116template<class InputIterator>
117inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700118readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700119
120
121/**
122 * @brief Read VAR-NUMBER in NDN-TLV encoding
123 *
124 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800125 *
126 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
127 */
128template<class InputIterator>
129inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700130readVarNumber(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800131
132/**
133 * @brief Read TLV Type
134 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700135 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
136 *
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800137 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
138 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
139 */
140template<class InputIterator>
141inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700142readType(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800143
144/**
145 * @brief Get number of bytes necessary to hold value of VAR-NUMBER
146 */
147inline size_t
148sizeOfVarNumber(uint64_t varNumber);
149
150/**
151 * @brief Write VAR-NUMBER to the specified stream
152 */
153inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700154writeVarNumber(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800155
156/**
157 * @brief Read nonNegativeInteger in NDN-TLV encoding
158 *
159 * This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
160 *
161 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
162 *
163 * How many bytes will be read is directly controlled by the size parameter, which can be either
164 * 1, 2, 4, or 8. If the value of size is different, then an exception will be thrown.
165 */
166template<class InputIterator>
167inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700168readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800169
170/**
171 * @brief Get number of bytes necessary to hold value of nonNegativeInteger
172 */
173inline size_t
174sizeOfNonNegativeInteger(uint64_t varNumber);
175
176/**
177 * @brief Write nonNegativeInteger to the specified stream
178 */
179inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700180writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800181
182/////////////////////////////////////////////////////////////////////////////////
183/////////////////////////////////////////////////////////////////////////////////
184/////////////////////////////////////////////////////////////////////////////////
185
186// Inline implementations
187
188/////////////////////////////////////////////////////////////////////////////////
189/////////////////////////////////////////////////////////////////////////////////
190/////////////////////////////////////////////////////////////////////////////////
191
192template<class InputIterator>
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700193inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700194readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700195{
196 if (begin == end)
197 return false;
198
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700199 uint8_t firstOctet = *begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700200 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700201 if (firstOctet < 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700202 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700203 number = firstOctet;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700204 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700205 else if (firstOctet == 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700206 {
207 if (end - begin < 2)
208 return false;
209
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700210 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700211 begin += 2;
212 number = be16toh(value);
213 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700214 else if (firstOctet == 254)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700215 {
216 if (end - begin < 4)
217 return false;
218
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700219 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700220 begin += 4;
221 number = be32toh(value);
222 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700223 else // if (firstOctet == 255)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700224 {
225 if (end - begin < 8)
226 return false;
227
228 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
229 begin += 8;
230
231 number = be64toh(value);
232 }
233
234 return true;
235}
236
237template<class InputIterator>
238inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700239readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700240{
Mickey Sweatt632e0572014-04-20 00:36:32 -0700241 uint64_t number = 0;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700242 bool isOk = readVarNumber(begin, end, number);
243 if (!isOk || number > std::numeric_limits<uint32_t>::max())
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700244 {
245 return false;
246 }
247
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700248 type = static_cast<uint64_t>(number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700249 return true;
250}
251
252template<class InputIterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800253inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700254readVarNumber(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800255{
256 if (begin == end)
257 throw Error("Empty buffer during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700258
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700259 uint64_t value;
260 bool isOk = readVarNumber(begin, end, value);
261 if (!isOk)
262 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700263
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700264 return value;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800265}
266
Yingdi Yu27158392014-01-20 13:04:20 -0800267template<>
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700268inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700269readVarNumber<std::istream_iterator<uint8_t> >(std::istream_iterator<uint8_t>& begin,
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700270 const std::istream_iterator<uint8_t>& end,
271 uint64_t& value)
Yingdi Yu27158392014-01-20 13:04:20 -0800272{
273 if (begin == end)
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700274 return false;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700275
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700276 uint8_t firstOctet = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800277 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700278 if (firstOctet < 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800279 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700280 value = firstOctet;
Yingdi Yu27158392014-01-20 13:04:20 -0800281 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700282 else if (firstOctet == 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800283 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700284 value = 0;
285 size_t count = 0;
286 for (; begin != end && count < 2; ++count)
287 {
288 value = ((value << 8) | *begin);
289 begin++;
290 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700291
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700292 if (count != 2)
293 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800294 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700295 else if (firstOctet == 254)
Yingdi Yu27158392014-01-20 13:04:20 -0800296 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700297 value = 0;
298 size_t count = 0;
299 for (; begin != end && count < 4; ++count)
300 {
301 value = ((value << 8) | *begin);
302 begin++;
303 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700304
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700305 if (count != 4)
306 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800307 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700308 else // if (firstOctet == 255)
Yingdi Yu27158392014-01-20 13:04:20 -0800309 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700310 value = 0;
311 size_t count = 0;
312 for (; begin != end && count < 8; ++count)
313 {
314 value = ((value << 8) | *begin);
315 begin++;
316 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700317
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700318 if (count != 8)
319 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800320 }
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700321
322 return true;
Yingdi Yu27158392014-01-20 13:04:20 -0800323}
324
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800325template<class InputIterator>
326inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700327readType(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800328{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700329 uint64_t type = readVarNumber(begin, end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800330 if (type > std::numeric_limits<uint32_t>::max())
331 {
332 throw Error("TLV type code exceeds allowed maximum");
333 }
334
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700335 return static_cast<uint32_t>(type);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800336}
337
338size_t
339sizeOfVarNumber(uint64_t varNumber)
340{
341 if (varNumber < 253) {
342 return 1;
343 }
344 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
345 return 3;
346 }
347 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
348 return 5;
349 }
350 else {
351 return 9;
352 }
353}
354
355inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700356writeVarNumber(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800357{
358 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200359 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800360 return 1;
361 }
362 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200363 os.put(static_cast<char>(253));
364 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700365 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800366 return 3;
367 }
368 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200369 os.put(static_cast<char>(254));
370 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700371 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800372 return 5;
373 }
374 else {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200375 os.put(static_cast<char>(255));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800376 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700377 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800378 return 9;
379 }
380}
381
382template<class InputIterator>
383inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700384readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800385{
386 switch (size) {
387 case 1:
388 {
389 if (end - begin < 1)
390 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700391
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800392 uint8_t value = *begin;
393 begin++;
394 return value;
395 }
396 case 2:
397 {
398 if (end - begin < 2)
399 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700400
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700401 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800402 begin += 2;
403 return be16toh(value);
404 }
405 case 4:
406 {
407 if (end - begin < 4)
408 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700409
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700410 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800411 begin += 4;
412 return be32toh(value);
413 }
414 case 8:
415 {
416 if (end - begin < 8)
417 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700418
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800419 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
420 begin += 8;
421 return be64toh(value);
422 }
423 }
424 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
425}
426
Yingdi Yu27158392014-01-20 13:04:20 -0800427template<>
428inline uint64_t
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700429readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700430 std::istream_iterator<uint8_t>& begin,
431 const std::istream_iterator<uint8_t>& end)
Yingdi Yu27158392014-01-20 13:04:20 -0800432{
433 switch (size) {
434 case 1:
435 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700436 if (begin == end)
Yingdi Yu27158392014-01-20 13:04:20 -0800437 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700438
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700439 uint64_t value = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800440 begin++;
441 return value;
442 }
443 case 2:
444 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700445 uint64_t value = 0;
446 size_t count = 0;
447 for (; begin != end && count < 2; ++count)
448 {
449 value = ((value << 8) | *begin);
450 begin++;
451 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700452
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700453 if (count != 2)
Yingdi Yu27158392014-01-20 13:04:20 -0800454 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700455
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700456 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800457 }
458 case 4:
459 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700460 uint64_t value = 0;
461 size_t count = 0;
462 for (; begin != end && count < 4; ++count)
463 {
464 value = ((value << 8) | *begin);
465 begin++;
466 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700467
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700468 if (count != 4)
Yingdi Yu27158392014-01-20 13:04:20 -0800469 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700470
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700471 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800472 }
473 case 8:
474 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700475 uint64_t value = 0;
476 size_t count = 0;
477 for (; begin != end && count < 8; ++count)
478 {
479 value = ((value << 8) | *begin);
480 begin++;
481 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700482
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700483 if (count != 8)
Yingdi Yu27158392014-01-20 13:04:20 -0800484 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700485
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700486 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800487 }
488 }
489 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
490}
491
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800492inline size_t
493sizeOfNonNegativeInteger(uint64_t varNumber)
494{
495 if (varNumber < 253) {
496 return 1;
497 }
498 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
499 return 2;
500 }
501 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
502 return 4;
503 }
504 else {
505 return 8;
506 }
507}
508
509
510inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700511writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800512{
513 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200514 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800515 return 1;
516 }
517 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200518 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700519 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800520 return 2;
521 }
522 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200523 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700524 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800525 return 4;
526 }
527 else {
528 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700529 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800530 return 8;
531 }
532}
533
534
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700535} // namespace Tlv
536
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800537} // namespace ndn
538
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700539#endif // NDN_ENCODING_TLV_HPP