blob: d207938cc921dbdd1b17fcd623b3c16fc8e2e31f [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/**
Junxiao Shi19d7a572016-07-26 12:55:09 +00003 * Copyright (c) 2013-2016 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_BLOCK_HELPERS_HPP
23#define NDN_ENCODING_BLOCK_HELPERS_HPP
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080024
25#include "block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070026#include "encoding-buffer.hpp"
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070027#include "../util/concepts.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080028
Alexander Afanasyev74633892015-02-08 18:08:46 -080029#include <iterator>
30
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080031namespace ndn {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070032namespace encoding {
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080033
Alexander Afanasyev74633892015-02-08 18:08:46 -080034/**
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070035 * @brief Helper to prepend TLV block type @p type containing non-negative integer @p value
36 * @see makeNonNegativeIntegerBlock, readNonNegativeInteger
Alexander Afanasyev74633892015-02-08 18:08:46 -080037 */
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070038template<Tag TAG>
39size_t
40prependNonNegativeIntegerBlock(EncodingImpl<TAG>& encoder, uint32_t type, uint64_t value);
Alexander Afanasyev74633892015-02-08 18:08:46 -080041
42/**
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070043 * @brief Create a TLV block type @p type containing non-negative integer @p value
44 * @see prependNonNegativeIntegerBlock, readNonNegativeInteger
Alexander Afanasyev74633892015-02-08 18:08:46 -080045 */
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070046Block
47makeNonNegativeIntegerBlock(uint32_t type, uint64_t value);
Alexander Afanasyev74633892015-02-08 18:08:46 -080048
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070049/**
50 * @brief Helper to read a non-negative integer from a block
51 * @see prependNonNegativeIntegerBlock, makeNonNegativeIntegerBlock
52 * @throw tlv::Error if block does not contain a valid nonNegativeInteger
53 */
54uint64_t
55readNonNegativeInteger(const Block& block);
Alexander Afanasyev74633892015-02-08 18:08:46 -080056
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070057////////
Alexander Afanasyev74633892015-02-08 18:08:46 -080058
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070059/**
60 * @brief Helper to prepend TLV block type @p type containing no value (i.e., a boolean block)
61 * @see makeEmptyBlock
62 */
63template<Tag TAG>
64size_t
65prependEmptyBlock(EncodingImpl<TAG>& encoder, uint32_t type);
Alexander Afanasyev74633892015-02-08 18:08:46 -080066
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070067/**
68 * @brief Create a TLV block type @p type containing no value (i.e., a boolean block)
69 * @see prependEmptyBlock
70 */
71Block
72makeEmptyBlock(uint32_t type);
Alexander Afanasyev74633892015-02-08 18:08:46 -080073
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070074////////
Alexander Afanasyev74633892015-02-08 18:08:46 -080075
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070076/**
77 * @brief Helper to prepend TLV block type @p type with value from a string @p value
78 * @see makeStringBlock, readString
79 */
80template<Tag TAG>
81size_t
82prependStringBlock(EncodingImpl<TAG>& encoder, uint32_t type, const std::string& value);
Alexander Afanasyev74633892015-02-08 18:08:46 -080083
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070084/**
Alexander Afanasyevf2a46222015-09-17 18:01:30 -070085 * @brief Create a TLV block type @p type with value from a string @p value
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070086 * @see prependStringBlock, readString
87 */
88Block
89makeStringBlock(uint32_t type, const std::string& value);
Alexander Afanasyev74633892015-02-08 18:08:46 -080090
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070091/**
92 * @brief Helper to read a string value from a block
93 * @see prependStringBlock, makeStringBlock
94 */
95std::string
96readString(const Block& block);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070097
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070098////////
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070099
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700100/**
101 * @brief Create a TLV block type @p type with value from a buffer @p value of size @p length
102 */
103Block
104makeBinaryBlock(uint32_t type, const uint8_t* value, size_t length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800105
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700106/**
107 * @brief Create a TLV block type @p type with value from a buffer @p value of size @p length
108 */
109Block
110makeBinaryBlock(uint32_t type, const char* value, size_t length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800111
Alexander Afanasyev74633892015-02-08 18:08:46 -0800112/**
113 * @brief Helper class template to create a data block when RandomAccessIterator is used
114 */
115template<class Iterator>
116class DataBlockFast
117{
118public:
119 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Iterator>));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800120
Alexander Afanasyev74633892015-02-08 18:08:46 -0800121 static Block
122 makeBlock(uint32_t type, Iterator first, Iterator last)
123 {
124 EncodingEstimator estimator;
125 size_t valueLength = last - first;
126 size_t totalLength = valueLength;
127 totalLength += estimator.prependVarNumber(valueLength);
128 totalLength += estimator.prependVarNumber(type);
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700129
Alexander Afanasyev74633892015-02-08 18:08:46 -0800130 EncodingBuffer encoder(totalLength, 0);
131 encoder.prependRange(first, last);
132 encoder.prependVarNumber(valueLength);
133 encoder.prependVarNumber(type);
134
135 return encoder.block();
136 }
137};
138
139/**
140 * @brief Helper class template to create a data block when generic InputIterator is used
141 */
142template<class Iterator>
143class DataBlockSlow
144{
145public:
146 BOOST_CONCEPT_ASSERT((boost::InputIterator<Iterator>));
147
148 static Block
149 makeBlock(uint32_t type, Iterator first, Iterator last)
150 {
151 // reserve 4 bytes in front (common for 1(type)-3(length) encoding
152 // Actual size will be adjusted as necessary by the encoder
153 EncodingBuffer encoder(4, 4);
154 size_t valueLength = encoder.appendRange(first, last);
155 encoder.prependVarNumber(valueLength);
156 encoder.prependVarNumber(type);
157
158 return encoder.block();
159 }
160};
161
162/**
163 * @brief Free function to create a block given @p type and range [@p first, @p last) of bytes
164 * @tparam Iterator iterator type satisfying at least InputIterator concept. Implementation
165 * is more optimal when the iterator type satisfies RandomAccessIterator concept
166 * It is required that sizeof(std::iterator_traits<Iterator>::value_type) == 1.
167 */
168template<class Iterator>
169inline Block
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700170makeBinaryBlock(uint32_t type, Iterator first, Iterator last)
Alexander Afanasyev74633892015-02-08 18:08:46 -0800171{
172 static_assert(sizeof(typename std::iterator_traits<Iterator>::value_type) == 1,
173 "Iterator should point only to char or unsigned char");
174
175 typedef typename boost::mpl::if_<
176 std::is_base_of<std::random_access_iterator_tag,
177 typename std::iterator_traits<Iterator>::iterator_category>,
178 DataBlockFast<Iterator>,
179 DataBlockSlow<Iterator>>::type DataBlock;
180
181 return DataBlock::makeBlock(type, first, last);
182}
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700183
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700184////////
185
186/**
187 * @brief Prepend a TLV block of type @p type with WireEncodable @p value as a value
188 * @tparam U type that satisfies WireEncodableWithEncodingBuffer concept
189 * @see makeNestedBlock
190 */
191template<Tag TAG, class U>
192inline size_t
193prependNestedBlock(EncodingImpl<TAG>& encoder, uint32_t type, const U& value)
194{
195 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<U>));
196
197 size_t valueLength = value.wireEncode(encoder);
198 size_t totalLength = valueLength;
199 totalLength += encoder.prependVarNumber(valueLength);
200 totalLength += encoder.prependVarNumber(type);
201
202 return totalLength;
203}
204
205/**
206 * @brief Create a TLV block of type @p type with WireEncodable @p value as a value
207 * @tparam U type that satisfies WireEncodableWithEncodingBuffer concept
208 * @see prependNestedBlock
209 */
210template<class U>
211inline Block
212makeNestedBlock(uint32_t type, const U& value)
213{
214 EncodingEstimator estimator;
215 size_t totalLength = prependNestedBlock(estimator, type, value);
216
217 EncodingBuffer encoder(totalLength, 0);
218 prependNestedBlock(encoder, type, value);
219
220 return encoder.block();
221}
222
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700223} // namespace encoding
224
225using encoding::makeNonNegativeIntegerBlock;
226using encoding::readNonNegativeInteger;
227using encoding::makeEmptyBlock;
228using encoding::makeStringBlock;
229using encoding::readString;
230using encoding::makeBinaryBlock;
231using encoding::makeNestedBlock;
232
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800233} // namespace ndn
234
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700235#endif // NDN_ENCODING_BLOCK_HELPERS_HPP