blob: 3c2d1e1abef094008a2888540accddd6667e952a [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi9da07c52017-08-06 16:59:30 +00002/*
Davide Pesaventodb4da5e2018-06-15 11:37:52 -04003 * Copyright (c) 2013-2018 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
29namespace ndn {
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070030namespace encoding {
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080031
Tianxing Ma241df422018-10-09 22:21:47 -050032/** @brief Prepend a TLV element containing a non-negative integer.
Junxiao Shi9da07c52017-08-06 16:59:30 +000033 * @param encoder an EncodingBuffer or EncodingEstimator
34 * @param type TLV-TYPE number
35 * @param value non-negative integer value
36 * @sa 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
Junxiao Shi9da07c52017-08-06 16:59:30 +000042extern template size_t
43prependNonNegativeIntegerBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t, uint64_t);
44
45extern template size_t
46prependNonNegativeIntegerBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t, uint64_t);
47
Tianxing Ma241df422018-10-09 22:21:47 -050048/** @brief Create a TLV block containing a non-negative integer.
Junxiao Shi9da07c52017-08-06 16:59:30 +000049 * @param type TLV-TYPE number
50 * @param value non-negative integer value
51 * @sa prependNonNegativeIntegerBlock, readNonNegativeInteger
Alexander Afanasyev74633892015-02-08 18:08:46 -080052 */
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070053Block
54makeNonNegativeIntegerBlock(uint32_t type, uint64_t value);
Alexander Afanasyev74633892015-02-08 18:08:46 -080055
Tianxing Ma241df422018-10-09 22:21:47 -050056/** @brief Read a non-negative integer from a TLV element.
Junxiao Shi9da07c52017-08-06 16:59:30 +000057 * @param block the TLV element
58 * @throw tlv::Error block does not contain a non-negative integer
59 * @sa prependNonNegativeIntegerBlock, makeNonNegativeIntegerBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070060 */
61uint64_t
62readNonNegativeInteger(const Block& block);
Alexander Afanasyev74633892015-02-08 18:08:46 -080063
Tianxing Ma241df422018-10-09 22:21:47 -050064/** @brief Read a non-negative integer from a TLV element and cast to the specified type.
Junxiao Shi5d75fd92017-08-08 18:09:20 +000065 * @tparam R result type, must be an integral type
66 * @param block the TLV element
67 * @throw tlv::Error block does not contain a valid non-negative integer or the number cannot be
68 * represented in R
69 */
70template<typename R>
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040071std::enable_if_t<std::is_integral<R>::value, R>
Junxiao Shi5d75fd92017-08-08 18:09:20 +000072readNonNegativeIntegerAs(const Block& block)
73{
74 uint64_t value = readNonNegativeInteger(block);
75 if (value > std::numeric_limits<R>::max()) {
76 BOOST_THROW_EXCEPTION(tlv::Error("Value in TLV element of type " + to_string(block.type()) +
77 " is too large"));
78 }
79 return static_cast<R>(value);
80}
81
Tianxing Ma241df422018-10-09 22:21:47 -050082/** @brief Read a non-negative integer from a TLV element and cast to the specified type.
Junxiao Shi5d75fd92017-08-08 18:09:20 +000083 * @tparam R result type, must be an enumeration type
84 * @param block the TLV element
85 * @throw tlv::Error block does not contain a valid non-negative integer or the number cannot be
86 * represented in R
87 * @warning If R is an unscoped enum type, it must have a fixed underlying type. Otherwise, this
88 * function may trigger unspecified behavior.
89 */
90template<typename R>
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040091std::enable_if_t<std::is_enum<R>::value, R>
Junxiao Shi5d75fd92017-08-08 18:09:20 +000092readNonNegativeIntegerAs(const Block& block)
93{
Davide Pesaventodb4da5e2018-06-15 11:37:52 -040094 return static_cast<R>(readNonNegativeIntegerAs<std::underlying_type_t<R>>(block));
Junxiao Shi5d75fd92017-08-08 18:09:20 +000095}
96
Tianxing Ma241df422018-10-09 22:21:47 -050097/** @brief Prepend an empty TLV element.
Junxiao Shi9da07c52017-08-06 16:59:30 +000098 * @param encoder an EncodingBuffer or EncodingEstimator
99 * @param type TLV-TYPE number
100 * @details The TLV element has zero-length TLV-VALUE.
101 * @sa makeEmptyBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700102 */
103template<Tag TAG>
104size_t
105prependEmptyBlock(EncodingImpl<TAG>& encoder, uint32_t type);
Alexander Afanasyev74633892015-02-08 18:08:46 -0800106
Junxiao Shi9da07c52017-08-06 16:59:30 +0000107extern template size_t
108prependEmptyBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t);
109
110extern template size_t
111prependEmptyBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t);
112
Tianxing Ma241df422018-10-09 22:21:47 -0500113/** @brief Create an empty TLV block.
Junxiao Shi9da07c52017-08-06 16:59:30 +0000114 * @param type TLV-TYPE number
115 * @return A TLV block with zero-length TLV-VALUE
116 * @sa prependEmptyBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700117 */
118Block
119makeEmptyBlock(uint32_t type);
Alexander Afanasyev74633892015-02-08 18:08:46 -0800120
Junxiao Shi9da07c52017-08-06 16:59:30 +0000121/** @brief Prepend a TLV element containing a string.
122 * @param encoder an EncodingBuffer or EncodingEstimator
123 * @param type TLV-TYPE number
124 * @param value string value, may contain NUL octets
125 * @sa makeStringBlock, readString
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700126 */
127template<Tag TAG>
128size_t
129prependStringBlock(EncodingImpl<TAG>& encoder, uint32_t type, const std::string& value);
Alexander Afanasyev74633892015-02-08 18:08:46 -0800130
Junxiao Shi9da07c52017-08-06 16:59:30 +0000131extern template size_t
132prependStringBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t, const std::string&);
133
134extern template size_t
135prependStringBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t, const std::string&);
136
137/** @brief Create a TLV block containing a string.
138 * @param type TLV-TYPE number
139 * @param value string value, may contain NUL octets
140 * @sa prependStringBlock, readString
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700141 */
142Block
143makeStringBlock(uint32_t type, const std::string& value);
Alexander Afanasyev74633892015-02-08 18:08:46 -0800144
Junxiao Shi9da07c52017-08-06 16:59:30 +0000145/** @brief Read TLV-VALUE of a TLV element as a string.
146 * @param block the TLV element
147 * @return a string, may contain NUL octets
148 * @sa prependStringBlock, makeStringBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700149 */
150std::string
151readString(const Block& block);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700152
Tianxing Ma241df422018-10-09 22:21:47 -0500153/** @brief Prepend a TLV element containing an IEEE 754 double-precision floating-point number.
154 * @param encoder an EncodingBuffer or EncodingEstimator
155 * @param type TLV-TYPE number
156 * @param value a floating point number value
157 * @sa makeDoubleBlock, readDouble
158 */
159template<Tag TAG>
160size_t
161prependDoubleBlock(EncodingImpl<TAG>& encoder, uint32_t type, double value);
162
163extern template size_t
164prependDoubleBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t, double);
165
166extern template size_t
167prependDoubleBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t, double);
168
169/** @brief Create a TLV element containing an IEEE 754 double-precision floating-point number.
170 * @param type TLV-TYPE number
171 * @param value floating point number value
172 * @sa prependDoubleBlock, readDouble
173 */
174Block
175makeDoubleBlock(uint32_t type, double value);
176
177/** @brief Read TLV-VALUE of a TLV element as an IEEE 754 double-precision floating-point number.
178 * @param block the TLV element
179 * @return a floating point number value
180 * @sa prependDoubleBlock, makeDoubleBlock
181 */
182double
183readDouble(const Block& block);
184
Junxiao Shi9da07c52017-08-06 16:59:30 +0000185/** @brief Create a TLV block copying TLV-VALUE from raw buffer.
186 * @param type TLV-TYPE number
187 * @param value raw buffer as TLV-VALUE
188 * @param length length of value buffer
189 * @sa Encoder::prependByteArrayBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700190 */
191Block
192makeBinaryBlock(uint32_t type, const uint8_t* value, size_t length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800193
Junxiao Shi9da07c52017-08-06 16:59:30 +0000194/** @brief Create a TLV block copying TLV-VALUE from raw buffer.
195 * @param type TLV-TYPE number
196 * @param value raw buffer as TLV-VALUE
197 * @param length length of value buffer
198 * @sa Encoder::prependByteArrayBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700199 */
200Block
201makeBinaryBlock(uint32_t type, const char* value, size_t length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800202
Junxiao Shi9da07c52017-08-06 16:59:30 +0000203namespace detail {
204
Tianxing Ma241df422018-10-09 22:21:47 -0500205/** @brief Create a binary block copying from RandomAccessIterator.
Alexander Afanasyev74633892015-02-08 18:08:46 -0800206 */
207template<class Iterator>
Junxiao Shi9da07c52017-08-06 16:59:30 +0000208class BinaryBlockFast
Alexander Afanasyev74633892015-02-08 18:08:46 -0800209{
210public:
211 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Iterator>));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800212
Alexander Afanasyev74633892015-02-08 18:08:46 -0800213 static Block
214 makeBlock(uint32_t type, Iterator first, Iterator last)
215 {
216 EncodingEstimator estimator;
217 size_t valueLength = last - first;
218 size_t totalLength = valueLength;
219 totalLength += estimator.prependVarNumber(valueLength);
220 totalLength += estimator.prependVarNumber(type);
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700221
Alexander Afanasyev74633892015-02-08 18:08:46 -0800222 EncodingBuffer encoder(totalLength, 0);
223 encoder.prependRange(first, last);
224 encoder.prependVarNumber(valueLength);
225 encoder.prependVarNumber(type);
226
227 return encoder.block();
228 }
229};
230
Tianxing Ma241df422018-10-09 22:21:47 -0500231/** @brief Create a binary block copying from generic InputIterator.
Alexander Afanasyev74633892015-02-08 18:08:46 -0800232 */
233template<class Iterator>
Junxiao Shi9da07c52017-08-06 16:59:30 +0000234class BinaryBlockSlow
Alexander Afanasyev74633892015-02-08 18:08:46 -0800235{
236public:
237 BOOST_CONCEPT_ASSERT((boost::InputIterator<Iterator>));
238
239 static Block
240 makeBlock(uint32_t type, Iterator first, Iterator last)
241 {
242 // reserve 4 bytes in front (common for 1(type)-3(length) encoding
243 // Actual size will be adjusted as necessary by the encoder
244 EncodingBuffer encoder(4, 4);
245 size_t valueLength = encoder.appendRange(first, last);
246 encoder.prependVarNumber(valueLength);
247 encoder.prependVarNumber(type);
248
249 return encoder.block();
250 }
251};
252
Junxiao Shi9da07c52017-08-06 16:59:30 +0000253} // namespace detail
254
255/** @brief Create a TLV block copying TLV-VALUE from iterators.
256 * @tparam Iterator an InputIterator dereferencable to an 1-octet type; faster implementation is
257 * available for RandomAccessIterator
258 * @param type TLV-TYPE number
259 * @param first begin iterator
260 * @param last past-the-end iterator
Alexander Afanasyev74633892015-02-08 18:08:46 -0800261 */
262template<class Iterator>
Junxiao Shi9da07c52017-08-06 16:59:30 +0000263Block
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700264makeBinaryBlock(uint32_t type, Iterator first, Iterator last)
Alexander Afanasyev74633892015-02-08 18:08:46 -0800265{
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400266 using BinaryBlockHelper = std::conditional_t<
Alexander Afanasyev74633892015-02-08 18:08:46 -0800267 std::is_base_of<std::random_access_iterator_tag,
Junxiao Shi9da07c52017-08-06 16:59:30 +0000268 typename std::iterator_traits<Iterator>::iterator_category>::value,
269 detail::BinaryBlockFast<Iterator>,
Davide Pesaventodb4da5e2018-06-15 11:37:52 -0400270 detail::BinaryBlockSlow<Iterator>>;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800271
Junxiao Shi9da07c52017-08-06 16:59:30 +0000272 return BinaryBlockHelper::makeBlock(type, first, last);
Alexander Afanasyev74633892015-02-08 18:08:46 -0800273}
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700274
Junxiao Shi9da07c52017-08-06 16:59:30 +0000275/** @brief Prepend a TLV element containing a nested TLV element.
276 * @tparam U type that satisfies WireEncodableWithEncodingBuffer concept
277 * @param encoder an EncodingBuffer or EncodingEstimator
278 * @param type TLV-TYPE number for outer TLV element
279 * @param value an object to be encoded as inner TLV element
280 * @sa makeNestedBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700281 */
282template<Tag TAG, class U>
Junxiao Shi9da07c52017-08-06 16:59:30 +0000283size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700284prependNestedBlock(EncodingImpl<TAG>& encoder, uint32_t type, const U& value)
285{
286 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<U>));
287
288 size_t valueLength = value.wireEncode(encoder);
289 size_t totalLength = valueLength;
290 totalLength += encoder.prependVarNumber(valueLength);
291 totalLength += encoder.prependVarNumber(type);
292
293 return totalLength;
294}
295
Junxiao Shi9da07c52017-08-06 16:59:30 +0000296/** @brief Create a TLV block containing a nested TLV element.
297 * @tparam U type that satisfies WireEncodableWithEncodingBuffer concept
298 * @param type TLV-TYPE number for outer TLV element
299 * @param value an object to be encoded as inner TLV element
300 * @sa prependNestedBlock
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700301 */
302template<class U>
Junxiao Shi9da07c52017-08-06 16:59:30 +0000303Block
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700304makeNestedBlock(uint32_t type, const U& value)
305{
306 EncodingEstimator estimator;
307 size_t totalLength = prependNestedBlock(estimator, type, value);
308
309 EncodingBuffer encoder(totalLength, 0);
310 prependNestedBlock(encoder, type, value);
311
312 return encoder.block();
313}
314
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700315} // namespace encoding
316
317using encoding::makeNonNegativeIntegerBlock;
318using encoding::readNonNegativeInteger;
Junxiao Shi5d75fd92017-08-08 18:09:20 +0000319using encoding::readNonNegativeIntegerAs;
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700320using encoding::makeEmptyBlock;
321using encoding::makeStringBlock;
322using encoding::readString;
323using encoding::makeBinaryBlock;
324using encoding::makeNestedBlock;
325
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800326} // namespace ndn
327
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700328#endif // NDN_ENCODING_BLOCK_HELPERS_HPP