block-helpers.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2022 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * 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.
20  */
21 
23 
24 #include <boost/endian/conversion.hpp>
25 
26 namespace ndn {
27 namespace encoding {
28 
29 namespace endian = boost::endian;
30 
31 // ---- non-negative integer ----
32 
33 template<Tag TAG>
34 size_t
35 prependNonNegativeIntegerBlock(EncodingImpl<TAG>& encoder, uint32_t type, uint64_t value)
36 {
37  size_t length = encoder.prependNonNegativeInteger(value);
38  length += encoder.prependVarNumber(length);
39  length += encoder.prependVarNumber(type);
40 
41  return length;
42 }
43 
44 template size_t
46 
47 template size_t
49 
50 Block
51 makeNonNegativeIntegerBlock(uint32_t type, uint64_t value)
52 {
53  EncodingEstimator estimator;
54  size_t totalLength = prependNonNegativeIntegerBlock(estimator, type, value);
55 
56  EncodingBuffer encoder(totalLength, 0);
57  prependNonNegativeIntegerBlock(encoder, type, value);
58 
59  return encoder.block();
60 }
61 
62 uint64_t
64 {
65  auto begin = block.value_begin();
66  return tlv::readNonNegativeInteger(block.value_size(), begin, block.value_end());
67 }
68 
69 // ---- empty ----
70 
71 template<Tag TAG>
72 size_t
73 prependEmptyBlock(EncodingImpl<TAG>& encoder, uint32_t type)
74 {
75  size_t length = encoder.prependVarNumber(0);
76  length += encoder.prependVarNumber(type);
77 
78  return length;
79 }
80 
81 template size_t
83 
84 template size_t
86 
87 Block
88 makeEmptyBlock(uint32_t type)
89 {
90  EncodingEstimator estimator;
91  size_t totalLength = prependEmptyBlock(estimator, type);
92 
93  EncodingBuffer encoder(totalLength, 0);
94  prependEmptyBlock(encoder, type);
95 
96  return encoder.block();
97 }
98 
99 // ---- string ----
100 
101 template<Tag TAG>
102 size_t
103 prependStringBlock(EncodingImpl<TAG>& encoder, uint32_t type, const std::string& value)
104 {
105  return prependBinaryBlock(encoder, type, {reinterpret_cast<const uint8_t*>(value.data()), value.size()});
106 }
107 
108 template size_t
109 prependStringBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t, const std::string&);
110 
111 template size_t
112 prependStringBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t, const std::string&);
113 
114 Block
115 makeStringBlock(uint32_t type, const std::string& value)
116 {
117  return makeBinaryBlock(type, value.data(), value.size());
118 }
119 
120 std::string
121 readString(const Block& block)
122 {
123  return std::string(reinterpret_cast<const char*>(block.value()), block.value_size());
124 }
125 
126 // ---- double ----
127 
128 static_assert(std::numeric_limits<double>::is_iec559, "This code requires IEEE-754 doubles");
129 
130 template<Tag TAG>
131 size_t
132 prependDoubleBlock(EncodingImpl<TAG>& encoder, uint32_t type, double value)
133 {
134  uint64_t temp = 0;
135  std::memcpy(&temp, &value, 8);
136  endian::native_to_big_inplace(temp);
137  return prependBinaryBlock(encoder, type, {reinterpret_cast<const uint8_t*>(&temp), 8});
138 }
139 
140 template size_t
142 
143 template size_t
145 
146 Block
147 makeDoubleBlock(uint32_t type, double value)
148 {
149  EncodingEstimator estimator;
150  size_t totalLength = prependDoubleBlock(estimator, type, value);
151 
152  EncodingBuffer encoder(totalLength, 0);
153  prependDoubleBlock(encoder, type, value);
154 
155  return encoder.block();
156 }
157 
158 double
159 readDouble(const Block& block)
160 {
161  if (block.value_size() != 8) {
162  NDN_THROW(tlv::Error("Invalid length for double (must be 8)"));
163  }
164 
165 #if BOOST_VERSION >= 107100
166  return endian::endian_load<double, 8, endian::order::big>(block.value());
167 #else
168  uint64_t temp = 0;
169  std::memcpy(&temp, block.value(), 8);
170  endian::big_to_native_inplace(temp);
171  double d = 0;
172  std::memcpy(&d, &temp, 8);
173  return d;
174 #endif
175 }
176 
177 // ---- binary ----
178 
179 template<Tag TAG>
180 size_t
181 prependBinaryBlock(EncodingImpl<TAG>& encoder, uint32_t type, span<const uint8_t> value)
182 {
183  size_t length = encoder.prependBytes(value);
184  length += encoder.prependVarNumber(length);
185  length += encoder.prependVarNumber(type);
186 
187  return length;
188 }
189 
190 template size_t
191 prependBinaryBlock<EstimatorTag>(EncodingImpl<EstimatorTag>&, uint32_t, span<const uint8_t>);
192 
193 template size_t
194 prependBinaryBlock<EncoderTag>(EncodingImpl<EncoderTag>&, uint32_t, span<const uint8_t>);
195 
196 Block
197 makeBinaryBlock(uint32_t type, span<const uint8_t> value)
198 {
199  EncodingEstimator estimator;
200  size_t totalLength = prependBinaryBlock(estimator, type, value);
201 
202  EncodingBuffer encoder(totalLength, 0);
203  prependBinaryBlock(encoder, type, value);
204 
205  return encoder.block();
206 }
207 
208 // ---- block ----
209 
210 template<Tag TAG>
211 size_t
212 prependBlock(EncodingImpl<TAG>& encoder, const Block& block)
213 {
214  if (block.hasWire()) {
215  return encoder.prependBytes(block);
216  }
217  else {
218  // FIXME: blindly calling Block::value_bytes() is not safe if the value is not wire-encoded
219  return prependBinaryBlock(encoder, block.type(), block.value_bytes());
220  }
221 }
222 
223 template size_t
225 
226 template size_t
228 
229 } // namespace encoding
230 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
const_iterator value_end() const noexcept
Get end iterator of TLV-VALUE.
Definition: block.hpp:311
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:221
span< const uint8_t > value_bytes() const noexcept
Return a read-only view of TLV-VALUE as a contiguous range of bytes.
Definition: block.hpp:330
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:277
const_iterator value_begin() const noexcept
Get begin iterator of TLV-VALUE.
Definition: block.hpp:301
size_t value_size() const noexcept
Return the size of TLV-VALUE, i.e., the TLV-LENGTH.
Definition: block.hpp:321
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
Definition: block.cpp:306
Block block(bool verifyLength=true) const
Create Block from the underlying buffer.
Definition: encoder.cpp:59
EncodingImpl specialization for actual TLV encoding.
EncodingImpl specialization for TLV size estimation.
Represents an error in TLV encoding or decoding.
Definition: tlv.hpp:54
#define NDN_THROW(e)
Definition: exception.hpp:61
template size_t prependEmptyBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, uint32_t)
template size_t prependDoubleBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, uint32_t, double)
template size_t prependBinaryBlock< EncoderTag >(EncodingImpl< EncoderTag > &, uint32_t, span< const uint8_t >)
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
template size_t prependStringBlock< EncoderTag >(EncodingImpl< EncoderTag > &, uint32_t, const std::string &)
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
size_t prependStringBlock(EncodingImpl< TAG > &encoder, uint32_t type, const std::string &value)
Prepend a TLV element containing a string.
template size_t prependBlock< EncoderTag >(EncodingImpl< EncoderTag > &, const Block &)
template size_t prependBinaryBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, uint32_t, span< const uint8_t >)
template size_t prependDoubleBlock< EncoderTag >(EncodingImpl< EncoderTag > &, uint32_t, double)
Block makeNonNegativeIntegerBlock(uint32_t type, uint64_t value)
Create a TLV block containing a non-negative integer.
Block makeEmptyBlock(uint32_t type)
Create an empty TLV block.
template size_t prependBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, const Block &)
template size_t prependNonNegativeIntegerBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, uint32_t, uint64_t)
size_t prependEmptyBlock(EncodingImpl< TAG > &encoder, uint32_t type)
Prepend an empty TLV element.
template size_t prependNonNegativeIntegerBlock< EncoderTag >(EncodingImpl< EncoderTag > &, uint32_t, uint64_t)
double readDouble(const Block &block)
Read TLV-VALUE of a TLV element as an IEEE 754 double-precision floating-point number.
template size_t prependEmptyBlock< EncoderTag >(EncodingImpl< EncoderTag > &, uint32_t)
template size_t prependStringBlock< EstimatorTag >(EncodingImpl< EstimatorTag > &, uint32_t, const std::string &)
Block makeBinaryBlock(uint32_t type, span< const uint8_t > value)
Create a TLV block copying the TLV-VALUE from a byte range.
size_t prependBinaryBlock(EncodingImpl< TAG > &encoder, uint32_t type, span< const uint8_t > value)
Prepend a TLV element containing a sequence of raw bytes.
std::string readString(const Block &block)
Read TLV-VALUE of a TLV element as a string.
size_t prependBlock(EncodingImpl< TAG > &encoder, const Block &block)
Prepend a TLV element.
Block makeStringBlock(uint32_t type, const std::string &value)
Create a TLV block containing a string.
Block makeDoubleBlock(uint32_t type, double value)
Create a TLV element containing an IEEE 754 double-precision floating-point number.
size_t prependDoubleBlock(EncodingImpl< TAG > &encoder, uint32_t type, double value)
Prepend a TLV element containing an IEEE 754 double-precision floating-point number.
uint64_t readNonNegativeInteger(size_t size, Iterator &begin, Iterator end)
Read a NonNegativeInteger in NDN-TLV encoding.
Definition: tlv.hpp:474
Definition: data.cpp:25