blob: d071a2e858e858c5f95ab96c249809749735e80b [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
3 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08005 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08008 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07009 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080011 */
12
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070013#ifndef NDN_ENCODING_TLV_HPP
14#define NDN_ENCODING_TLV_HPP
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015
Alexander Afanasyev54467af2014-01-06 15:45:32 -080016#include <stdexcept>
Yingdi Yu27158392014-01-20 13:04:20 -080017#include <iterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080018#include "buffer.hpp"
Alexander Afanasyev200dd6f2014-01-28 19:04:25 -080019#include "endian.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080020
21namespace ndn {
22
23/**
24 * @brief Namespace defining NDN-TLV related constants and procedures
25 */
26namespace Tlv {
27
Alexander Afanasyeva465e972014-03-22 17:21:49 -070028class Error : public std::runtime_error
29{
30public:
31 explicit
32 Error(const std::string& what)
33 : std::runtime_error(what)
34 {
35 }
36};
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080037
38enum {
Alexander Afanasyev4b456282014-02-13 00:34:34 -080039 Interest = 5,
40 Data = 6,
41 Name = 7,
42 NameComponent = 8,
43 Selectors = 9,
44 Nonce = 10,
Alexander Afanasyeva465e972014-03-22 17:21:49 -070045 Scope = 11, // deprecated
Alexander Afanasyev4b456282014-02-13 00:34:34 -080046 InterestLifetime = 12,
47 MinSuffixComponents = 13,
48 MaxSuffixComponents = 14,
49 PublisherPublicKeyLocator = 15,
50 Exclude = 16,
51 ChildSelector = 17,
52 MustBeFresh = 18,
53 Any = 19,
54 MetaInfo = 20,
55 Content = 21,
56 SignatureInfo = 22,
57 SignatureValue = 23,
58 ContentType = 24,
59 FreshnessPeriod = 25,
60 FinalBlockId = 26,
61 SignatureType = 27,
62 KeyLocator = 28,
63 KeyLocatorDigest = 29,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080064
65 AppPrivateBlock1 = 128,
66 AppPrivateBlock2 = 32767
67};
68
69enum SignatureType {
70 DigestSha256 = 0,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070071 SignatureSha256WithRsa = 1
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080072};
73
74enum ConentType {
75 ContentType_Default = 0,
76 ContentType_Link = 1,
Alexander Afanasyevb78bc4d2014-04-09 21:20:52 -070077 ContentType_Key = 2
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080078};
79
80/**
81 * @brief Read VAR-NUMBER in NDN-TLV encoding
82 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -070083 * @param [in] begin Begin (pointer or iterator) of the buffer
84 * @param [in] end End (pointer or iterator) of the buffer
85 * @param [out] number Read number
86 *
87 * @throws This call never throws exception
88 *
89 * @return true if number successfully read from input, false otherwise
90 */
91template<class InputIterator>
92inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -070093readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070094
95/**
96 * @brief Read TLV Type
97 *
98 * @param [in] begin Begin (pointer or iterator) of the buffer
99 * @param [in] end End (pointer or iterator) of the buffer
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700100 * @param [out] type Read type number
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700101 *
102 * @throws This call never throws exception
103 *
104 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
105 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
106 */
107template<class InputIterator>
108inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700109readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700110
111
112/**
113 * @brief Read VAR-NUMBER in NDN-TLV encoding
114 *
115 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800116 *
117 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
118 */
119template<class InputIterator>
120inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700121readVarNumber(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800122
123/**
124 * @brief Read TLV Type
125 *
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700126 * @throws This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
127 *
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800128 * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
129 * is larger than 2^32-1 (type in this library is implemented as uint32_t)
130 */
131template<class InputIterator>
132inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700133readType(InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800134
135/**
136 * @brief Get number of bytes necessary to hold value of VAR-NUMBER
137 */
138inline size_t
139sizeOfVarNumber(uint64_t varNumber);
140
141/**
142 * @brief Write VAR-NUMBER to the specified stream
143 */
144inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700145writeVarNumber(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800146
147/**
148 * @brief Read nonNegativeInteger in NDN-TLV encoding
149 *
150 * This call will throw ndn::Tlv::Error (aka std::runtime_error) if number cannot be read
151 *
152 * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
153 *
154 * How many bytes will be read is directly controlled by the size parameter, which can be either
155 * 1, 2, 4, or 8. If the value of size is different, then an exception will be thrown.
156 */
157template<class InputIterator>
158inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700159readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800160
161/**
162 * @brief Get number of bytes necessary to hold value of nonNegativeInteger
163 */
164inline size_t
165sizeOfNonNegativeInteger(uint64_t varNumber);
166
167/**
168 * @brief Write nonNegativeInteger to the specified stream
169 */
170inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700171writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800172
173/////////////////////////////////////////////////////////////////////////////////
174/////////////////////////////////////////////////////////////////////////////////
175/////////////////////////////////////////////////////////////////////////////////
176
177// Inline implementations
178
179/////////////////////////////////////////////////////////////////////////////////
180/////////////////////////////////////////////////////////////////////////////////
181/////////////////////////////////////////////////////////////////////////////////
182
183template<class InputIterator>
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700184inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700185readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700186{
187 if (begin == end)
188 return false;
189
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700190 uint8_t firstOctet = *begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700191 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700192 if (firstOctet < 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700193 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700194 number = firstOctet;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700195 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700196 else if (firstOctet == 253)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700197 {
198 if (end - begin < 2)
199 return false;
200
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700201 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700202 begin += 2;
203 number = be16toh(value);
204 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700205 else if (firstOctet == 254)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700206 {
207 if (end - begin < 4)
208 return false;
209
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700210 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700211 begin += 4;
212 number = be32toh(value);
213 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700214 else // if (firstOctet == 255)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700215 {
216 if (end - begin < 8)
217 return false;
218
219 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
220 begin += 8;
221
222 number = be64toh(value);
223 }
224
225 return true;
226}
227
228template<class InputIterator>
229inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700230readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700231{
Mickey Sweatt632e0572014-04-20 00:36:32 -0700232 uint64_t number = 0;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700233 bool isOk = readVarNumber(begin, end, number);
234 if (!isOk || number > std::numeric_limits<uint32_t>::max())
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700235 {
236 return false;
237 }
238
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700239 type = static_cast<uint64_t>(number);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700240 return true;
241}
242
243template<class InputIterator>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800244inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700245readVarNumber(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800246{
247 if (begin == end)
248 throw Error("Empty buffer during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700249
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700250 uint64_t value;
251 bool isOk = readVarNumber(begin, end, value);
252 if (!isOk)
253 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700254
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700255 return value;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800256}
257
Yingdi Yu27158392014-01-20 13:04:20 -0800258template<>
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700259inline bool
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700260readVarNumber<std::istream_iterator<uint8_t> >(std::istream_iterator<uint8_t>& begin,
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700261 const std::istream_iterator<uint8_t>& end,
262 uint64_t& value)
Yingdi Yu27158392014-01-20 13:04:20 -0800263{
264 if (begin == end)
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700265 return false;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700266
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700267 uint8_t firstOctet = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800268 ++begin;
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700269 if (firstOctet < 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800270 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700271 value = firstOctet;
Yingdi Yu27158392014-01-20 13:04:20 -0800272 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700273 else if (firstOctet == 253)
Yingdi Yu27158392014-01-20 13:04:20 -0800274 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700275 value = 0;
276 size_t count = 0;
277 for (; begin != end && count < 2; ++count)
278 {
279 value = ((value << 8) | *begin);
280 begin++;
281 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700282
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700283 if (count != 2)
284 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800285 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700286 else if (firstOctet == 254)
Yingdi Yu27158392014-01-20 13:04:20 -0800287 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700288 value = 0;
289 size_t count = 0;
290 for (; begin != end && count < 4; ++count)
291 {
292 value = ((value << 8) | *begin);
293 begin++;
294 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700295
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700296 if (count != 4)
297 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800298 }
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700299 else // if (firstOctet == 255)
Yingdi Yu27158392014-01-20 13:04:20 -0800300 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700301 value = 0;
302 size_t count = 0;
303 for (; begin != end && count < 8; ++count)
304 {
305 value = ((value << 8) | *begin);
306 begin++;
307 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700308
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700309 if (count != 8)
310 return false;
Yingdi Yu27158392014-01-20 13:04:20 -0800311 }
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700312
313 return true;
Yingdi Yu27158392014-01-20 13:04:20 -0800314}
315
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800316template<class InputIterator>
317inline uint32_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700318readType(InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800319{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700320 uint64_t type = readVarNumber(begin, end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800321 if (type > std::numeric_limits<uint32_t>::max())
322 {
323 throw Error("TLV type code exceeds allowed maximum");
324 }
325
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700326 return static_cast<uint32_t>(type);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800327}
328
329size_t
330sizeOfVarNumber(uint64_t varNumber)
331{
332 if (varNumber < 253) {
333 return 1;
334 }
335 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
336 return 3;
337 }
338 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
339 return 5;
340 }
341 else {
342 return 9;
343 }
344}
345
346inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700347writeVarNumber(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800348{
349 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200350 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800351 return 1;
352 }
353 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200354 os.put(static_cast<char>(253));
355 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700356 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800357 return 3;
358 }
359 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200360 os.put(static_cast<char>(254));
361 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700362 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800363 return 5;
364 }
365 else {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200366 os.put(static_cast<char>(255));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800367 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700368 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800369 return 9;
370 }
371}
372
373template<class InputIterator>
374inline uint64_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700375readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800376{
377 switch (size) {
378 case 1:
379 {
380 if (end - begin < 1)
381 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700382
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800383 uint8_t value = *begin;
384 begin++;
385 return value;
386 }
387 case 2:
388 {
389 if (end - begin < 2)
390 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700391
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700392 uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800393 begin += 2;
394 return be16toh(value);
395 }
396 case 4:
397 {
398 if (end - begin < 4)
399 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700400
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700401 uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800402 begin += 4;
403 return be32toh(value);
404 }
405 case 8:
406 {
407 if (end - begin < 8)
408 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700409
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800410 uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
411 begin += 8;
412 return be64toh(value);
413 }
414 }
415 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
416}
417
Yingdi Yu27158392014-01-20 13:04:20 -0800418template<>
419inline uint64_t
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700420readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700421 std::istream_iterator<uint8_t>& begin,
422 const std::istream_iterator<uint8_t>& end)
Yingdi Yu27158392014-01-20 13:04:20 -0800423{
424 switch (size) {
425 case 1:
426 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700427 if (begin == end)
Yingdi Yu27158392014-01-20 13:04:20 -0800428 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700429
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700430 uint64_t value = *begin;
Yingdi Yu27158392014-01-20 13:04:20 -0800431 begin++;
432 return value;
433 }
434 case 2:
435 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700436 uint64_t value = 0;
437 size_t count = 0;
438 for (; begin != end && count < 2; ++count)
439 {
440 value = ((value << 8) | *begin);
441 begin++;
442 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700443
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700444 if (count != 2)
Yingdi Yu27158392014-01-20 13:04:20 -0800445 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700446
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700447 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800448 }
449 case 4:
450 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700451 uint64_t value = 0;
452 size_t count = 0;
453 for (; begin != end && count < 4; ++count)
454 {
455 value = ((value << 8) | *begin);
456 begin++;
457 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700458
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700459 if (count != 4)
Yingdi Yu27158392014-01-20 13:04:20 -0800460 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700461
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700462 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800463 }
464 case 8:
465 {
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700466 uint64_t value = 0;
467 size_t count = 0;
468 for (; begin != end && count < 8; ++count)
469 {
470 value = ((value << 8) | *begin);
471 begin++;
472 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700473
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700474 if (count != 8)
Yingdi Yu27158392014-01-20 13:04:20 -0800475 throw Error("Insufficient data during TLV processing");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700476
Alexander Afanasyev21ef2392014-03-25 12:40:22 -0700477 return value;
Yingdi Yu27158392014-01-20 13:04:20 -0800478 }
479 }
480 throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
481}
482
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800483inline size_t
484sizeOfNonNegativeInteger(uint64_t varNumber)
485{
486 if (varNumber < 253) {
487 return 1;
488 }
489 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
490 return 2;
491 }
492 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
493 return 4;
494 }
495 else {
496 return 8;
497 }
498}
499
500
501inline size_t
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700502writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800503{
504 if (varNumber < 253) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200505 os.put(static_cast<char>(varNumber));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800506 return 1;
507 }
508 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200509 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700510 os.write(reinterpret_cast<const char*>(&value), 2);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800511 return 2;
512 }
513 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
Davide Pesavento07ffe0d2014-04-10 20:21:55 +0200514 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700515 os.write(reinterpret_cast<const char*>(&value), 4);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800516 return 4;
517 }
518 else {
519 uint64_t value = htobe64(varNumber);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700520 os.write(reinterpret_cast<const char*>(&value), 8);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800521 return 8;
522 }
523}
524
525
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700526} // namespace Tlv
527
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800528} // namespace ndn
529
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700530#endif // NDN_ENCODING_TLV_HPP