encoder.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 Encoder::Encoder(size_t totalReserve, size_t reserveFromBack)
32  : m_buffer(make_shared<Buffer>(totalReserve))
33 {
34  m_begin = m_end = m_buffer->end() - (reserveFromBack < totalReserve ? reserveFromBack : 0);
35 }
36 
37 Encoder::Encoder(const Block& block)
38  : m_buffer(const_pointer_cast<Buffer>(block.getBuffer()))
39  , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
40  , m_end(m_buffer->begin() + (block.end() - m_buffer->begin()))
41 {
42 }
43 
44 void
46 {
47  if (m_end + size > m_buffer->end())
48  reserve(m_buffer->size() * 2 + size, false);
49 }
50 
51 void
53 {
54  if (m_buffer->begin() + size > m_begin)
55  reserve(m_buffer->size() * 2 + size, true);
56 }
57 
58 Block
59 Encoder::block(bool verifyLength) const
60 {
61  return Block(m_buffer, m_begin, m_end, verifyLength);
62 }
63 
64 void
65 Encoder::reserve(size_t size, bool addInFront)
66 {
67  if (size < m_buffer->size()) {
68  size = m_buffer->size();
69  }
70 
71  if (addInFront) {
72  size_t diffEnd = m_buffer->end() - m_end;
73  size_t diffBegin = m_buffer->end() - m_begin;
74 
75  Buffer* buf = new Buffer(size);
76  std::copy_backward(m_buffer->begin(), m_buffer->end(), buf->end());
77 
78  m_buffer.reset(buf);
79 
80  m_end = m_buffer->end() - diffEnd;
81  m_begin = m_buffer->end() - diffBegin;
82  }
83  else {
84  size_t diffEnd = m_end - m_buffer->begin();
85  size_t diffBegin = m_begin - m_buffer->begin();
86 
87  Buffer* buf = new Buffer(size);
88  std::copy(m_buffer->begin(), m_buffer->end(), buf->begin());
89 
90  m_buffer.reset(buf);
91 
92  m_end = m_buffer->begin() + diffEnd;
93  m_begin = m_buffer->begin() + diffBegin;
94  }
95 }
96 
97 size_t
98 Encoder::prependBytes(span<const uint8_t> bytes)
99 {
100  return prependRange(bytes.begin(), bytes.end());
101 }
102 
103 size_t
104 Encoder::appendBytes(span<const uint8_t> bytes)
105 {
106  return appendRange(bytes.begin(), bytes.end());
107 }
108 
109 size_t
110 Encoder::prependVarNumber(uint64_t varNumber)
111 {
112  if (varNumber < 253) {
113  prependBytes({static_cast<uint8_t>(varNumber)});
114  return 1;
115  }
116  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
117  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
118  prependBytes({reinterpret_cast<const uint8_t*>(&value), 2});
119  prependBytes({253});
120  return 3;
121  }
122  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
123  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
124  prependBytes({reinterpret_cast<const uint8_t*>(&value), 4});
125  prependBytes({254});
126  return 5;
127  }
128  else {
129  uint64_t value = endian::native_to_big(varNumber);
130  prependBytes({reinterpret_cast<const uint8_t*>(&value), 8});
131  prependBytes({255});
132  return 9;
133  }
134 }
135 
136 size_t
137 Encoder::appendVarNumber(uint64_t varNumber)
138 {
139  if (varNumber < 253) {
140  appendBytes({static_cast<uint8_t>(varNumber)});
141  return 1;
142  }
143  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
144  appendBytes({253});
145  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
146  appendBytes({reinterpret_cast<const uint8_t*>(&value), 2});
147  return 3;
148  }
149  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
150  appendBytes({254});
151  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
152  appendBytes({reinterpret_cast<const uint8_t*>(&value), 4});
153  return 5;
154  }
155  else {
156  appendBytes({255});
157  uint64_t value = endian::native_to_big(varNumber);
158  appendBytes({reinterpret_cast<const uint8_t*>(&value), 8});
159  return 9;
160  }
161 }
162 
163 size_t
165 {
166  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
167  return prependBytes({static_cast<uint8_t>(varNumber)});
168  }
169  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
170  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
171  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 2});
172  }
173  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
174  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
175  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 4});
176  }
177  else {
178  uint64_t value = endian::native_to_big(varNumber);
179  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 8});
180  }
181 }
182 
183 size_t
185 {
186  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
187  return appendBytes({static_cast<uint8_t>(varNumber)});
188  }
189  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
190  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
191  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 2});
192  }
193  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
194  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
195  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 4});
196  }
197  else {
198  uint64_t value = endian::native_to_big(varNumber);
199  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 8});
200  }
201 }
202 
203 size_t
204 Encoder::prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
205 {
206  size_t totalLength = prependBytes({array, arraySize});
207  totalLength += prependVarNumber(arraySize);
208  totalLength += prependVarNumber(type);
209 
210  return totalLength;
211 }
212 
213 size_t
214 Encoder::appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
215 {
216  size_t totalLength = appendVarNumber(type);
217  totalLength += appendVarNumber(arraySize);
218  totalLength += appendBytes({array, arraySize});
219 
220  return totalLength;
221 }
222 
223 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
224 
225 size_t
227 {
228  if (block.hasWire()) {
229  return prependBytes({block.wire(), block.size()});
230  }
231  else {
233  }
234 }
235 
236 size_t
238 {
239  if (block.hasWire()) {
240  return appendBytes({block.wire(), block.size()});
241  }
242  else {
244  }
245 }
246 
247 } // namespace encoding
248 } // namespace ndn
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
const uint8_t * wire() const
Return a raw pointer to the beginning of the encoded wire.
Definition: block.cpp:296
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:285
size_t size() const
Return the size of the encoded wire, i.e.
Definition: block.cpp:305
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:241
size_t value_size() const noexcept
Return the size of TLV-VALUE, aka TLV-LENGTH.
Definition: block.cpp:323
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
Definition: block.cpp:317
General-purpose automatically managed/resized buffer.
Definition: buffer.hpp:42
void reserve(size_t size, bool addInFront)
Reserve size bytes for the underlying buffer.
Definition: encoder.cpp:65
size_t size() const noexcept
Returns the size of the encoded buffer.
Definition: encoder.hpp:321
Encoder(size_t totalReserve=MAX_NDN_PACKET_SIZE, size_t reserveFromBack=400)
Create instance of the encoder with the specified reserved sizes.
Definition: encoder.cpp:31
size_t appendBytes(span< const uint8_t > bytes)
Append a sequence of bytes.
Definition: encoder.cpp:104
void reserveFront(size_t size)
Reserve at least isze bytes at the beginning of the underlying buffer.
Definition: encoder.cpp:52
Block block(bool verifyLength=true) const
Create Block from the underlying buffer.
Definition: encoder.cpp:59
uint8_t * buf() noexcept
Definition: encoder.hpp:302
size_t prependBytes(span< const uint8_t > bytes)
Prepend a sequence of bytes.
Definition: encoder.cpp:98
size_t prependRange(Iterator first, Iterator last)
Prepend range of bytes from the range [first, last)
Definition: encoder.hpp:347
size_t prependVarNumber(uint64_t number)
Prepend number encoded as a VAR-NUMBER in NDN-TLV format.
Definition: encoder.cpp:110
size_t prependNonNegativeInteger(uint64_t integer)
Prepend integer encoded as a NonNegativeInteger in NDN-TLV format.
Definition: encoder.cpp:164
size_t appendByteArrayBlock(uint32_t type, const uint8_t *array, size_t arraySize)
Append TLV block of type type and value from buffer array of size arraySize.
Definition: encoder.cpp:214
size_t appendBlock(const Block &block)
Append TLV block block.
Definition: encoder.cpp:237
size_t appendNonNegativeInteger(uint64_t integer)
Append integer encoded as a NonNegativeInteger in NDN-TLV format.
Definition: encoder.cpp:184
size_t appendRange(Iterator first, Iterator last)
Append range of bytes from the range [first, last)
Definition: encoder.hpp:362
size_t appendVarNumber(uint64_t number)
Append number encoded as a VAR-NUMBER in NDN-TLV format.
Definition: encoder.cpp:137
void reserveBack(size_t size)
Reserve at least size bytes at the back of the underlying buffer.
Definition: encoder.cpp:45
size_t prependBlock(const Block &block)
Prepend TLV block block.
Definition: encoder.cpp:226
size_t prependByteArrayBlock(uint32_t type, const uint8_t *array, size_t arraySize)
Prepend TLV block of type type and value from buffer array of size arraySize.
Definition: encoder.cpp:204
Definition: data.cpp:25