blob: b253a8a21075fd5ae6e02630ed08a146bc74b903 [file] [log] [blame]
Alexander Afanasyev74633892015-02-08 18:08:46 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi5c9ee282017-08-13 17:06:09 +00002/*
Davide Pesavento570b20d2018-07-15 21:53:14 -04003 * Copyright (c) 2013-2018 Regents of the University of California.
Alexander Afanasyev74633892015-02-08 18:08:46 -08004 *
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
22#ifndef NDN_ENCODING_ENCODER_HPP
23#define NDN_ENCODING_ENCODER_HPP
24
Alexander Afanasyev74633892015-02-08 18:08:46 -080025#include "block.hpp"
26
27namespace ndn {
28namespace encoding {
29
30/**
31 * @brief Helper class to perform TLV encoding
32 * Interface of this class (mostly) matches interface of Estimator class
33 * @sa Estimator
34 */
Davide Pesavento570b20d2018-07-15 21:53:14 -040035class Encoder : noncopyable
Alexander Afanasyev74633892015-02-08 18:08:46 -080036{
37public: // common interface between Encoder and Estimator
38 /**
Alexander Afanasyev74633892015-02-08 18:08:46 -080039 * @brief Prepend a byte
40 */
41 size_t
42 prependByte(uint8_t value);
43
44 /**
45 * @brief Append a byte
46 */
47 size_t
48 appendByte(uint8_t value);
49
50 /**
51 * @brief Prepend a byte array @p array of length @p length
52 */
53 size_t
54 prependByteArray(const uint8_t* array, size_t length);
55
56 /**
57 * @brief Append a byte array @p array of length @p length
58 */
59 size_t
60 appendByteArray(const uint8_t* array, size_t length);
61
62 /**
63 * @brief Prepend range of bytes from the range [@p first, @p last)
64 */
65 template<class Iterator>
66 size_t
67 prependRange(Iterator first, Iterator last);
68
69 /**
70 * @brief Append range of bytes from the range [@p first, @p last)
71 */
72 template<class Iterator>
73 size_t
74 appendRange(Iterator first, Iterator last);
75
76 /**
77 * @brief Prepend VarNumber @p varNumber of NDN TLV encoding
78 * @sa http://named-data.net/doc/ndn-tlv/
79 */
80 size_t
81 prependVarNumber(uint64_t varNumber);
82
83 /**
84 * @brief Prepend VarNumber @p varNumber of NDN TLV encoding
85 * @sa http://named-data.net/doc/ndn-tlv/
86 */
87 size_t
88 appendVarNumber(uint64_t varNumber);
89
90 /**
91 * @brief Prepend non-negative integer @p integer of NDN TLV encoding
92 * @sa http://named-data.net/doc/ndn-tlv/
93 */
94 size_t
95 prependNonNegativeInteger(uint64_t integer);
96
97 /**
98 * @brief Append non-negative integer @p integer of NDN TLV encoding
99 * @sa http://named-data.net/doc/ndn-tlv/
100 */
101 size_t
102 appendNonNegativeInteger(uint64_t integer);
103
104 /**
105 * @brief Prepend TLV block of type @p type and value from buffer @p array of size @p arraySize
106 */
107 size_t
108 prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize);
109
110 /**
111 * @brief Append TLV block of type @p type and value from buffer @p array of size @p arraySize
112 */
113 size_t
114 appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize);
115
116 /**
117 * @brief Prepend TLV block @p block
118 */
119 size_t
120 prependBlock(const Block& block);
121
122 /**
123 * @brief Append TLV block @p block
124 */
125 size_t
126 appendBlock(const Block& block);
127
128public: // unique interface to the Encoder
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000129 using value_type = Buffer::value_type;
130 using iterator = Buffer::iterator;
131 using const_iterator = Buffer::const_iterator;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800132
133 /**
Davide Pesavento570b20d2018-07-15 21:53:14 -0400134 * @brief Create instance of the encoder with the specified reserved sizes
135 * @param totalReserve initial buffer size to reserve
136 * @param reserveFromBack number of bytes to reserve for append* operations
137 */
138 explicit
139 Encoder(size_t totalReserve = MAX_NDN_PACKET_SIZE, size_t reserveFromBack = 400);
140
141 /**
Alexander Afanasyev74633892015-02-08 18:08:46 -0800142 * @brief Create EncodingBlock from existing block
143 *
144 * This is a dangerous constructor and should be used with caution.
145 * It will modify contents of the buffer that is used by block and may
146 * impact data in other blocks.
147 *
148 * The primary purpose for this method is to be used to extend Block
149 * after sign operation.
150 */
151 explicit
152 Encoder(const Block& block);
153
154 /**
155 * @brief Reserve @p size bytes for the underlying buffer
Alexander Afanasyevf2a46222015-09-17 18:01:30 -0700156 * @param size amount of bytes to reserve in the underlying buffer
Alexander Afanasyev74633892015-02-08 18:08:46 -0800157 * @param addInFront if true, then @p size bytes will be available in front (i.e., subsequent call
158 * to prepend* will not need to allocate memory). If false, then reservation will be done
159 * at the end of the buffer (i.d., for subsequent append* calls)
160 * @note Reserve size is exact, unlike reserveFront and reserveBack methods
161 * @sa reserveFront, reserveBack
162 */
163 void
164 reserve(size_t size, bool addInFront);
165
166 /**
167 * @brief Reserve at least @p size bytes at the back of the underlying buffer
168 * @note the actual reserve size can be (and in most cases is) larger than specified reservation
169 * length
170 */
171 void
172 reserveBack(size_t size);
173
174 /**
175 * @brief Reserve at least @p isze bytes at the beginning of the underlying buffer
176 * @note the actual reserve size can be (and in most cases is) larger than specified reservation
177 * length
178 */
179 void
180 reserveFront(size_t size);
181
182 /**
183 * @brief Get size of the underlying buffer
184 */
185 size_t
Davide Pesavento570b20d2018-07-15 21:53:14 -0400186 capacity() const noexcept;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800187
188 /**
189 * @brief Get underlying buffer
190 */
191 shared_ptr<Buffer>
Davide Pesavento570b20d2018-07-15 21:53:14 -0400192 getBuffer() const noexcept;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800193
194public: // accessors
Alexander Afanasyev74633892015-02-08 18:08:46 -0800195 /**
196 * @brief Get an iterator pointing to the first byte of the encoded buffer
197 */
198 iterator
199 begin();
200
201 /**
202 * @brief Get an iterator pointing to the past-the-end byte of the encoded buffer
203 */
204 iterator
205 end();
206
207 /**
208 * @brief Get an iterator pointing to the first byte of the encoded buffer
209 */
210 const_iterator
211 begin() const;
212
Davide Pesavento570b20d2018-07-15 21:53:14 -0400213 /**
214 * @brief Get an iterator pointing to the past-the-end byte of the encoded buffer
215 */
Alexander Afanasyev74633892015-02-08 18:08:46 -0800216 const_iterator
217 end() const;
218
219 /**
220 * @brief Get a pointer to the first byte of the encoded buffer
221 */
222 uint8_t*
223 buf();
224
225 /**
226 * @brief Get a pointer to the first byte of the encoded buffer
227 */
228 const uint8_t*
229 buf() const;
230
231 /**
Davide Pesavento570b20d2018-07-15 21:53:14 -0400232 * @brief Get the size of the encoded buffer
Alexander Afanasyev74633892015-02-08 18:08:46 -0800233 */
234 size_t
Davide Pesavento570b20d2018-07-15 21:53:14 -0400235 size() const noexcept;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800236
237 /**
238 * @brief Create Block from the underlying buffer
239 *
240 * @param verifyLength If this parameter set to true, Block's constructor
241 * will be requested to verify consistency of the encoded
242 * length in the Block, otherwise ignored
243 */
244 Block
245 block(bool verifyLength = true) const;
246
247private:
248 shared_ptr<Buffer> m_buffer;
249
250 // invariant: m_begin always points to the position of last-written byte (if prepending data)
251 iterator m_begin;
252 // invariant: m_end always points to the position of next unwritten byte (if appending data)
253 iterator m_end;
254};
255
Alexander Afanasyev74633892015-02-08 18:08:46 -0800256inline size_t
Davide Pesavento570b20d2018-07-15 21:53:14 -0400257Encoder::size() const noexcept
Alexander Afanasyev74633892015-02-08 18:08:46 -0800258{
259 return m_end - m_begin;
260}
261
262inline shared_ptr<Buffer>
Davide Pesavento570b20d2018-07-15 21:53:14 -0400263Encoder::getBuffer() const noexcept
Alexander Afanasyev74633892015-02-08 18:08:46 -0800264{
265 return m_buffer;
266}
267
268inline size_t
Davide Pesavento570b20d2018-07-15 21:53:14 -0400269Encoder::capacity() const noexcept
Alexander Afanasyev74633892015-02-08 18:08:46 -0800270{
271 return m_buffer->size();
272}
273
274inline Buffer::iterator
275Encoder::begin()
276{
277 return m_begin;
278}
279
280inline Buffer::iterator
281Encoder::end()
282{
283 return m_end;
284}
285
286inline Buffer::const_iterator
287Encoder::begin() const
288{
289 return m_begin;
290}
291
292inline Buffer::const_iterator
293Encoder::end() const
294{
295 return m_end;
296}
297
298inline uint8_t*
299Encoder::buf()
300{
301 return &(*m_begin);
302}
303
304inline const uint8_t*
305Encoder::buf() const
306{
307 return &(*m_begin);
308}
309
310template<class Iterator>
Davide Pesavento570b20d2018-07-15 21:53:14 -0400311size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800312Encoder::prependRange(Iterator first, Iterator last)
313{
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000314 using ValueType = typename std::iterator_traits<Iterator>::value_type;
315 static_assert(sizeof(ValueType) == 1 && !std::is_same<ValueType, bool>::value, "");
316
Alexander Afanasyev74633892015-02-08 18:08:46 -0800317 size_t length = std::distance(first, last);
318 reserveFront(length);
319
320 m_begin -= length;
321 std::copy(first, last, m_begin);
322 return length;
323}
324
Alexander Afanasyev74633892015-02-08 18:08:46 -0800325template<class Iterator>
Davide Pesavento570b20d2018-07-15 21:53:14 -0400326size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800327Encoder::appendRange(Iterator first, Iterator last)
328{
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000329 using ValueType = typename std::iterator_traits<Iterator>::value_type;
330 static_assert(sizeof(ValueType) == 1 && !std::is_same<ValueType, bool>::value, "");
331
Alexander Afanasyev74633892015-02-08 18:08:46 -0800332 size_t length = std::distance(first, last);
333 reserveBack(length);
334
335 std::copy(first, last, m_end);
336 m_end += length;
337 return length;
338}
339
Alexander Afanasyev74633892015-02-08 18:08:46 -0800340} // namespace encoding
341} // namespace ndn
342
343#endif // NDN_ENCODING_ENCODER_HPP