| 
    
       /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * Copyright (c) 2013-2014 Regents of the University of California.
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 
     | 
  
  
     | 
    
        * terms of the GNU Lesser General Public License as published by the Free Software
 
     | 
  
  
     | 
    
        * Foundation, either version 3 of the License, or (at your option) any later version.
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 
     | 
  
  
     | 
    
        * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 
     | 
  
  
     | 
    
        * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * You should have received copies of the GNU General Public License and GNU Lesser
 
     | 
  
  
     | 
    
        * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 
     | 
  
  
     | 
    
        * <http://www.gnu.org/licenses/>.
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #ifndef NDN_ENCODING_TLV_HPP
 
     | 
  
  
     | 
    
       #define NDN_ENCODING_TLV_HPP
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #include <stdexcept>
 
     | 
  
  
     | 
    
       #include <iostream>
 
     | 
  
  
     | 
    
       #include <iterator>
 
     | 
  
  
     | 
    
       #include <limits>
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #include "buffer.hpp"
 
     | 
  
  
     | 
    
       #include "endian.hpp"
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       namespace ndn {
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /** @brief practical limit of network layer packet size
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        *  If a packet is longer than this size, library and application MAY drop it.
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       const size_t MAX_NDN_PACKET_SIZE = 10000000;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Namespace defining NDN-TLV related constants and procedures
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       namespace tlv {
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /** @brief represents an error in TLV encoding or decoding
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        *  Element::Error SHOULD inherit from this Error class.
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       class Error : public std::runtime_error
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
       public:
 
     | 
  
  
     | 
    
         explicit
 
     | 
  
  
     | 
    
         Error(const std::string& what)
 
     | 
  
  
     | 
    
           : std::runtime_error(what)
 
     | 
  
  
     | 
    
         {
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       enum {
 
     | 
  
  
     | 
    
         Interest      = 5,
 
     | 
  
  
     | 
    
         Data          = 6,
 
     | 
  
  
     | 
    
         Name          = 7,
 
     | 
  
  
     | 
    
         ImplicitSha256DigestComponent = 1,
 
     | 
  
  
     | 
    
         NameComponent = 8,
 
     | 
  
  
     | 
    
         Selectors     = 9,
 
     | 
  
  
     | 
    
         Nonce         = 10,
 
     | 
  
  
     | 
    
         Scope         = 11, // deprecated
 
     | 
  
  
     | 
    
         InterestLifetime          = 12,
 
     | 
  
  
     | 
    
         MinSuffixComponents       = 13,
 
     | 
  
  
     | 
    
         MaxSuffixComponents       = 14,
 
     | 
  
  
     | 
    
         PublisherPublicKeyLocator = 15,
 
     | 
  
  
     | 
    
         Exclude       = 16,
 
     | 
  
  
     | 
    
         ChildSelector = 17,
 
     | 
  
  
     | 
    
         MustBeFresh   = 18,
 
     | 
  
  
     | 
    
         Any           = 19,
 
     | 
  
  
     | 
    
         MetaInfo      = 20,
 
     | 
  
  
     | 
    
         Content       = 21,
 
     | 
  
  
     | 
    
         SignatureInfo = 22,
 
     | 
  
  
     | 
    
         SignatureValue  = 23,
 
     | 
  
  
     | 
    
         ContentType     = 24,
 
     | 
  
  
     | 
    
         FreshnessPeriod = 25,
 
     | 
  
  
     | 
    
         FinalBlockId  = 26,
 
     | 
  
  
     | 
    
         SignatureType = 27,
 
     | 
  
  
     | 
    
         KeyLocator    = 28,
 
     | 
  
  
     | 
    
         KeyDigest     = 29,
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         AppPrivateBlock1 = 128,
 
     | 
  
  
     | 
    
         AppPrivateBlock2 = 32767
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       enum SignatureTypeValue {
 
     | 
  
  
     | 
    
         DigestSha256 = 0,
 
     | 
  
  
     | 
    
         SignatureSha256WithRsa = 1,
 
     | 
  
  
     | 
    
         SignatureSha256WithEcdsa = 3
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /** @brief indicates a possible value of ContentType field
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       enum ContentTypeValue {
 
     | 
  
  
     | 
    
         /** @brief indicates content is the actual data bits
 
     | 
  
  
     | 
    
          */
 
     | 
  
  
     | 
    
         ContentType_Blob = 0,
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         /** @brief indicates content is another name which identifies actual data content
 
     | 
  
  
     | 
    
          */
 
     | 
  
  
     | 
    
         ContentType_Link = 1,
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         /** @brief indicates content is a public key
 
     | 
  
  
     | 
    
          */
 
     | 
  
  
     | 
    
         ContentType_Key = 2,
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         /** @brief indicates a producer generated NACK
 
     | 
  
  
     | 
    
          *  @warning Experimental. Not defined in NDN-TLV spec.
 
     | 
  
  
     | 
    
          */
 
     | 
  
  
     | 
    
         ContentType_Nack = 3
 
     | 
  
  
     | 
    
       };
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /** @deprecated use ContentType_Blob
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       static const uint32_t DEPRECATED(ContentType_Default) = ContentType_Blob;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Read VAR-NUMBER in NDN-TLV encoding
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @param [in]  begin  Begin (pointer or iterator) of the buffer
 
     | 
  
  
     | 
    
        * @param [in]  end    End (pointer or iterator) of the buffer
 
     | 
  
  
     | 
    
        * @param [out] number Read number
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @throws This call never throws exception
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @return true if number successfully read from input, false otherwise
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline bool
 
     | 
  
  
     | 
    
       readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Read TLV Type
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @param [in]  begin  Begin (pointer or iterator) of the buffer
 
     | 
  
  
     | 
    
        * @param [in]  end    End (pointer or iterator) of the buffer
 
     | 
  
  
     | 
    
        * @param [out] type   Read type number
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @throws This call never throws exception
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
 
     | 
  
  
     | 
    
        * is larger than 2^32-1 (type in this library is implemented as uint32_t)
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline bool
 
     | 
  
  
     | 
    
       readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Read VAR-NUMBER in NDN-TLV encoding
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @throws This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint64_t
 
     | 
  
  
     | 
    
       readVarNumber(InputIterator& begin, const InputIterator& end);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Read TLV Type
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * @throws This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
 
     | 
  
  
     | 
    
        * is larger than 2^32-1 (type in this library is implemented as uint32_t)
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint32_t
 
     | 
  
  
     | 
    
       readType(InputIterator& begin, const InputIterator& end);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Get number of bytes necessary to hold value of VAR-NUMBER
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       sizeOfVarNumber(uint64_t varNumber);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Write VAR-NUMBER to the specified stream
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       writeVarNumber(std::ostream& os, uint64_t varNumber);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Read nonNegativeInteger in NDN-TLV encoding
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
 
     | 
  
  
     | 
    
        *
 
     | 
  
  
     | 
    
        * How many bytes will be read is directly controlled by the size parameter, which can be either
 
     | 
  
  
     | 
    
        * 1, 2, 4, or 8.  If the value of size is different, then an exception will be thrown.
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint64_t
 
     | 
  
  
     | 
    
       readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Get number of bytes necessary to hold value of nonNegativeInteger
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       sizeOfNonNegativeInteger(uint64_t varNumber);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /**
 
     | 
  
  
     | 
    
        * @brief Write nonNegativeInteger to the specified stream
 
     | 
  
  
     | 
    
        */
 
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       // Inline implementations
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       /////////////////////////////////////////////////////////////////////////////////
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline bool
 
     | 
  
  
     | 
    
       readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (begin == end)
 
     | 
  
  
     | 
    
           return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         uint8_t firstOctet = *begin;
 
     | 
  
  
     | 
    
         ++begin;
 
     | 
  
  
     | 
    
         if (firstOctet < 253)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             number = firstOctet;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else if (firstOctet == 253)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 2)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 2;
 
     | 
  
  
     | 
    
             number = be16toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else if (firstOctet == 254)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 4)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 4;
 
     | 
  
  
     | 
    
             number = be32toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else // if (firstOctet == 255)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 8)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 8;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             number = be64toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         return true;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline bool
 
     | 
  
  
     | 
    
       readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         uint64_t number = 0;
 
     | 
  
  
     | 
    
         bool isOk = readVarNumber(begin, end, number);
 
     | 
  
  
     | 
    
         if (!isOk || number > std::numeric_limits<uint32_t>::max())
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             return false;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         type = static_cast<uint64_t>(number);
 
     | 
  
  
     | 
    
         return true;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint64_t
 
     | 
  
  
     | 
    
       readVarNumber(InputIterator& begin, const InputIterator& end)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (begin == end)
 
     | 
  
  
     | 
    
           throw Error("Empty buffer during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         uint64_t value;
 
     | 
  
  
     | 
    
         bool isOk = readVarNumber(begin, end, value);
 
     | 
  
  
     | 
    
         if (!isOk)
 
     | 
  
  
     | 
    
           throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         return value;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<>
 
     | 
  
  
     | 
    
       inline bool
 
     | 
  
  
     | 
    
       readVarNumber<std::istream_iterator<uint8_t>>(std::istream_iterator<uint8_t>& begin,
 
     | 
  
  
     | 
    
                                                     const std::istream_iterator<uint8_t>& end,
 
     | 
  
  
     | 
    
                                                     uint64_t& value)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (begin == end)
 
     | 
  
  
     | 
    
           return false;
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         uint8_t firstOctet = *begin;
 
     | 
  
  
     | 
    
         ++begin;
 
     | 
  
  
     | 
    
         if (firstOctet < 253)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             value = firstOctet;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else if (firstOctet == 253)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 2; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 2)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else if (firstOctet == 254)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 4; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 4)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         else // if (firstOctet == 255)
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 8; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 8)
 
     | 
  
  
     | 
    
               return false;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         return true;
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint32_t
 
     | 
  
  
     | 
    
       readType(InputIterator& begin, const InputIterator& end)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         uint64_t type = readVarNumber(begin, end);
 
     | 
  
  
     | 
    
         if (type > std::numeric_limits<uint32_t>::max())
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             throw Error("TLV type code exceeds allowed maximum");
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
         return static_cast<uint32_t>(type);
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       size_t
 
     | 
  
  
     | 
    
       sizeOfVarNumber(uint64_t varNumber)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (varNumber < 253) {
 
     | 
  
  
     | 
    
           return 1;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
 
     | 
  
  
     | 
    
           return 3;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
 
     | 
  
  
     | 
    
           return 5;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else {
 
     | 
  
  
     | 
    
           return 9;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       writeVarNumber(std::ostream& os, uint64_t varNumber)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (varNumber < 253) {
 
     | 
  
  
     | 
    
           os.put(static_cast<char>(varNumber));
 
     | 
  
  
     | 
    
           return 1;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
 
     | 
  
  
     | 
    
           os.put(static_cast<char>(253));
 
     | 
  
  
     | 
    
           uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 2);
 
     | 
  
  
     | 
    
           return 3;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
 
     | 
  
  
     | 
    
           os.put(static_cast<char>(254));
 
     | 
  
  
     | 
    
           uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 4);
 
     | 
  
  
     | 
    
           return 5;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else {
 
     | 
  
  
     | 
    
           os.put(static_cast<char>(255));
 
     | 
  
  
     | 
    
           uint64_t value = htobe64(varNumber);
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 8);
 
     | 
  
  
     | 
    
           return 9;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<class InputIterator>
 
     | 
  
  
     | 
    
       inline uint64_t
 
     | 
  
  
     | 
    
       readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         switch (size) {
 
     | 
  
  
     | 
    
         case 1:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 1)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint8_t value = *begin;
 
     | 
  
  
     | 
    
             begin++;
 
     | 
  
  
     | 
    
             return value;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 2:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 2)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 2;
 
     | 
  
  
     | 
    
             return be16toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 4:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 4)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 4;
 
     | 
  
  
     | 
    
             return be32toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 8:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (end - begin < 8)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
 
     | 
  
  
     | 
    
             begin += 8;
 
     | 
  
  
     | 
    
             return be64toh(value);
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       template<>
 
     | 
  
  
     | 
    
       inline uint64_t
 
     | 
  
  
     | 
    
       readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
 
     | 
  
  
     | 
    
                                                               std::istream_iterator<uint8_t>& begin,
 
     | 
  
  
     | 
    
                                                               const std::istream_iterator<uint8_t>& end)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         switch (size) {
 
     | 
  
  
     | 
    
         case 1:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             if (begin == end)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             uint64_t value = *begin;
 
     | 
  
  
     | 
    
             begin++;
 
     | 
  
  
     | 
    
             return value;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 2:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             uint64_t value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 2; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 2)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             return value;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 4:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             uint64_t value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 4; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 4)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             return value;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         case 8:
 
     | 
  
  
     | 
    
           {
 
     | 
  
  
     | 
    
             uint64_t value = 0;
 
     | 
  
  
     | 
    
             size_t count = 0;
 
     | 
  
  
     | 
    
             for (; begin != end && count < 8; ++count)
 
     | 
  
  
     | 
    
               {
 
     | 
  
  
     | 
    
                 value = ((value << 8) | *begin);
 
     | 
  
  
     | 
    
                 begin++;
 
     | 
  
  
     | 
    
               }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             if (count != 8)
 
     | 
  
  
     | 
    
               throw Error("Insufficient data during TLV processing");
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
             return value;
 
     | 
  
  
     | 
    
           }
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         throw Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)");
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       sizeOfNonNegativeInteger(uint64_t varNumber)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (varNumber < 253) {
 
     | 
  
  
     | 
    
           return 1;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
 
     | 
  
  
     | 
    
           return 2;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
 
     | 
  
  
     | 
    
           return 4;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else {
 
     | 
  
  
     | 
    
           return 8;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       inline size_t
 
     | 
  
  
     | 
    
       writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
 
     | 
  
  
     | 
    
       {
 
     | 
  
  
     | 
    
         if (varNumber < 253) {
 
     | 
  
  
     | 
    
           os.put(static_cast<char>(varNumber));
 
     | 
  
  
     | 
    
           return 1;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
 
     | 
  
  
     | 
    
           uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 2);
 
     | 
  
  
     | 
    
           return 2;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
 
     | 
  
  
     | 
    
           uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 4);
 
     | 
  
  
     | 
    
           return 4;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
         else {
 
     | 
  
  
     | 
    
           uint64_t value = htobe64(varNumber);
 
     | 
  
  
     | 
    
           os.write(reinterpret_cast<const char*>(&value), 8);
 
     | 
  
  
     | 
    
           return 8;
 
     | 
  
  
     | 
    
         }
 
     | 
  
  
     | 
    
       }
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       } // namespace tlv
 
     | 
  
  
     | 
    
       } // namespace ndn
 
     | 
  
  
     | 
    
       
     | 
  
  
     | 
    
       #endif // NDN_ENCODING_TLV_HPP
 
     |