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-2018 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 
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::prependByte(uint8_t value)
99 {
100  reserveFront(1);
101 
102  m_begin--;
103  *m_begin = value;
104  return 1;
105 }
106 
107 size_t
108 Encoder::appendByte(uint8_t value)
109 {
110  reserveBack(1);
111 
112  *m_end = value;
113  m_end++;
114  return 1;
115 }
116 
117 size_t
118 Encoder::prependByteArray(const uint8_t* array, size_t length)
119 {
120  reserveFront(length);
121 
122  m_begin -= length;
123  std::copy(array, array + length, m_begin);
124  return length;
125 }
126 
127 size_t
128 Encoder::appendByteArray(const uint8_t* array, size_t length)
129 {
130  reserveBack(length);
131 
132  std::copy(array, array + length, m_end);
133  m_end += length;
134  return length;
135 }
136 
137 size_t
138 Encoder::prependVarNumber(uint64_t varNumber)
139 {
140  if (varNumber < 253) {
141  prependByte(static_cast<uint8_t>(varNumber));
142  return 1;
143  }
144  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
145  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
146  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
147  prependByte(253);
148  return 3;
149  }
150  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
151  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
152  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
153  prependByte(254);
154  return 5;
155  }
156  else {
157  uint64_t value = endian::native_to_big(varNumber);
158  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
159  prependByte(255);
160  return 9;
161  }
162 }
163 
164 size_t
165 Encoder::appendVarNumber(uint64_t varNumber)
166 {
167  if (varNumber < 253) {
168  appendByte(static_cast<uint8_t>(varNumber));
169  return 1;
170  }
171  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
172  appendByte(253);
173  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
174  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
175  return 3;
176  }
177  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
178  appendByte(254);
179  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
180  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
181  return 5;
182  }
183  else {
184  appendByte(255);
185  uint64_t value = endian::native_to_big(varNumber);
186  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
187  return 9;
188  }
189 }
190 
191 size_t
193 {
194  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
195  return prependByte(static_cast<uint8_t>(varNumber));
196  }
197  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
198  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
199  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
200  }
201  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
202  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
203  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
204  }
205  else {
206  uint64_t value = endian::native_to_big(varNumber);
207  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
208  }
209 }
210 
211 size_t
213 {
214  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
215  return appendByte(static_cast<uint8_t>(varNumber));
216  }
217  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
218  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
219  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
220  }
221  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
222  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
223  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
224  }
225  else {
226  uint64_t value = endian::native_to_big(varNumber);
227  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
228  }
229 }
230 
231 size_t
232 Encoder::prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
233 {
234  size_t totalLength = prependByteArray(array, arraySize);
235  totalLength += prependVarNumber(arraySize);
236  totalLength += prependVarNumber(type);
237 
238  return totalLength;
239 }
240 
241 size_t
242 Encoder::appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
243 {
244  size_t totalLength = appendVarNumber(type);
245  totalLength += appendVarNumber(arraySize);
246  totalLength += appendByteArray(array, arraySize);
247 
248  return totalLength;
249 }
250 
251 size_t
253 {
254  if (block.hasWire()) {
255  return prependByteArray(block.wire(), block.size());
256  }
257  else {
258  return prependByteArrayBlock(block.type(), block.value(), block.value_size());
259  }
260 }
261 
262 size_t
264 {
265  if (block.hasWire()) {
266  return appendByteArray(block.wire(), block.size());
267  }
268  else {
269  return appendByteArrayBlock(block.type(), block.value(), block.value_size());
270  }
271 }
272 
273 } // namespace encoding
274 } // namespace ndn
size_t prependByteArray(const uint8_t *array, size_t length)
Prepend a byte array array of length length.
Definition: encoder.cpp:118
void reserveFront(size_t size)
Reserve at least isze bytes at the beginning of the underlying buffer.
Definition: encoder.cpp:52
size_t appendVarNumber(uint64_t varNumber)
Prepend VarNumber varNumber of NDN TLV encoding.
Definition: encoder.cpp:165
iterator begin()
Get an iterator pointing to the first byte of the encoded buffer.
Definition: encoder.hpp:275
Definition: data.cpp:26
size_t prependByte(uint8_t value)
Prepend a byte.
Definition: encoder.cpp:98
iterator end()
Get an iterator pointing to the past-the-end byte of the encoded buffer.
Definition: encoder.hpp:281
size_t value_size() const noexcept
Return the size of TLV-VALUE, aka TLV-LENGTH.
Definition: block.cpp:307
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
void reserve(size_t size, bool addInFront)
Reserve size bytes for the underlying buffer.
Definition: encoder.cpp:65
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:230
size_t size() const noexcept
Get the size of the encoded buffer.
Definition: encoder.hpp:257
void reserveBack(size_t size)
Reserve at least size bytes at the back of the underlying buffer.
Definition: encoder.cpp:45
size_t size() const
Return the size of the encoded wire, i.e.
Definition: block.cpp:289
size_t prependVarNumber(uint64_t varNumber)
Prepend VarNumber varNumber of NDN TLV encoding.
Definition: encoder.cpp:138
size_t prependBlock(const Block &block)
Prepend TLV block block.
Definition: encoder.cpp:252
size_t appendBlock(const Block &block)
Append TLV block block.
Definition: encoder.cpp:263
shared_ptr< Buffer > getBuffer() const noexcept
Get underlying buffer.
Definition: encoder.hpp:263
Block block(bool verifyLength=true) const
Create Block from the underlying buffer.
Definition: encoder.cpp:59
size_t appendByte(uint8_t value)
Append a byte.
Definition: encoder.cpp:108
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:232
size_t appendByteArray(const uint8_t *array, size_t length)
Append a byte array array of length length.
Definition: encoder.cpp:128
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:274
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
Definition: block.cpp:301
uint8_t * buf()
Get a pointer to the first byte of the encoded buffer.
Definition: encoder.hpp:299
const uint8_t * wire() const
Return a raw pointer to the beginning of the encoded wire.
Definition: block.cpp:280
size_t prependNonNegativeInteger(uint64_t integer)
Prepend non-negative integer integer of NDN TLV encoding.
Definition: encoder.cpp:192
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:242
size_t appendNonNegativeInteger(uint64_t integer)
Append non-negative integer integer of NDN TLV encoding.
Definition: encoder.cpp:212
General-purpose automatically managed/resized buffer.
Definition: buffer.hpp:40
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