blob: 06a7ca13d874fadfd22130fc996df8316d325084 [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/*
3 * Copyright (c) 2013-2017 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 */
35class Encoder
36{
37public: // common interface between Encoder and Estimator
38 /**
39 * @brief Create instance of the encoder with the specified reserved sizes
Davide Pesavento18cf81b2015-09-12 23:36:43 +020040 * @param totalReserve initial buffer size to reserve
41 * @param reserveFromBack number of bytes to reserve for append* operations
Alexander Afanasyev74633892015-02-08 18:08:46 -080042 */
43 explicit
susmit8b156552016-01-12 13:10:55 -070044 Encoder(size_t totalReserve = MAX_NDN_PACKET_SIZE, size_t reserveFromBack = 400);
Alexander Afanasyev74633892015-02-08 18:08:46 -080045
46 Encoder(const Encoder&) = delete;
47
48 Encoder&
49 operator=(const Encoder&) = delete;
50
51 /**
52 * @brief Prepend a byte
53 */
54 size_t
55 prependByte(uint8_t value);
56
57 /**
58 * @brief Append a byte
59 */
60 size_t
61 appendByte(uint8_t value);
62
63 /**
64 * @brief Prepend a byte array @p array of length @p length
65 */
66 size_t
67 prependByteArray(const uint8_t* array, size_t length);
68
69 /**
70 * @brief Append a byte array @p array of length @p length
71 */
72 size_t
73 appendByteArray(const uint8_t* array, size_t length);
74
75 /**
76 * @brief Prepend range of bytes from the range [@p first, @p last)
77 */
78 template<class Iterator>
79 size_t
80 prependRange(Iterator first, Iterator last);
81
82 /**
83 * @brief Append range of bytes from the range [@p first, @p last)
84 */
85 template<class Iterator>
86 size_t
87 appendRange(Iterator first, Iterator last);
88
89 /**
90 * @brief Prepend VarNumber @p varNumber of NDN TLV encoding
91 * @sa http://named-data.net/doc/ndn-tlv/
92 */
93 size_t
94 prependVarNumber(uint64_t varNumber);
95
96 /**
97 * @brief Prepend VarNumber @p varNumber of NDN TLV encoding
98 * @sa http://named-data.net/doc/ndn-tlv/
99 */
100 size_t
101 appendVarNumber(uint64_t varNumber);
102
103 /**
104 * @brief Prepend non-negative integer @p integer of NDN TLV encoding
105 * @sa http://named-data.net/doc/ndn-tlv/
106 */
107 size_t
108 prependNonNegativeInteger(uint64_t integer);
109
110 /**
111 * @brief Append non-negative integer @p integer of NDN TLV encoding
112 * @sa http://named-data.net/doc/ndn-tlv/
113 */
114 size_t
115 appendNonNegativeInteger(uint64_t integer);
116
117 /**
118 * @brief Prepend TLV block of type @p type and value from buffer @p array of size @p arraySize
119 */
120 size_t
121 prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize);
122
123 /**
124 * @brief Append TLV block of type @p type and value from buffer @p array of size @p arraySize
125 */
126 size_t
127 appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize);
128
129 /**
130 * @brief Prepend TLV block @p block
131 */
132 size_t
133 prependBlock(const Block& block);
134
135 /**
136 * @brief Append TLV block @p block
137 */
138 size_t
139 appendBlock(const Block& block);
140
141public: // unique interface to the Encoder
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000142 using value_type = Buffer::value_type;
143 using iterator = Buffer::iterator;
144 using const_iterator = Buffer::const_iterator;
Alexander Afanasyev74633892015-02-08 18:08:46 -0800145
146 /**
147 * @brief Create EncodingBlock from existing block
148 *
149 * This is a dangerous constructor and should be used with caution.
150 * It will modify contents of the buffer that is used by block and may
151 * impact data in other blocks.
152 *
153 * The primary purpose for this method is to be used to extend Block
154 * after sign operation.
155 */
156 explicit
157 Encoder(const Block& block);
158
159 /**
160 * @brief Reserve @p size bytes for the underlying buffer
Alexander Afanasyevf2a46222015-09-17 18:01:30 -0700161 * @param size amount of bytes to reserve in the underlying buffer
Alexander Afanasyev74633892015-02-08 18:08:46 -0800162 * @param addInFront if true, then @p size bytes will be available in front (i.e., subsequent call
163 * to prepend* will not need to allocate memory). If false, then reservation will be done
164 * at the end of the buffer (i.d., for subsequent append* calls)
165 * @note Reserve size is exact, unlike reserveFront and reserveBack methods
166 * @sa reserveFront, reserveBack
167 */
168 void
169 reserve(size_t size, bool addInFront);
170
171 /**
172 * @brief Reserve at least @p size bytes at the back of the underlying buffer
173 * @note the actual reserve size can be (and in most cases is) larger than specified reservation
174 * length
175 */
176 void
177 reserveBack(size_t size);
178
179 /**
180 * @brief Reserve at least @p isze bytes at the beginning of the underlying buffer
181 * @note the actual reserve size can be (and in most cases is) larger than specified reservation
182 * length
183 */
184 void
185 reserveFront(size_t size);
186
187 /**
188 * @brief Get size of the underlying buffer
189 */
190 size_t
191 capacity() const;
192
193 /**
194 * @brief Get underlying buffer
195 */
196 shared_ptr<Buffer>
197 getBuffer();
198
199public: // accessors
200
201 /**
202 * @brief Get an iterator pointing to the first byte of the encoded buffer
203 */
204 iterator
205 begin();
206
207 /**
208 * @brief Get an iterator pointing to the past-the-end byte of the encoded buffer
209 */
210 iterator
211 end();
212
213 /**
214 * @brief Get an iterator pointing to the first byte of the encoded buffer
215 */
216 const_iterator
217 begin() const;
218
219 const_iterator
220 end() const;
221
222 /**
223 * @brief Get a pointer to the first byte of the encoded buffer
224 */
225 uint8_t*
226 buf();
227
228 /**
229 * @brief Get a pointer to the first byte of the encoded buffer
230 */
231 const uint8_t*
232 buf() const;
233
234 /**
235 * @brief Get size of the encoded buffer
236 */
237 size_t
238 size() const;
239
240 /**
241 * @brief Create Block from the underlying buffer
242 *
243 * @param verifyLength If this parameter set to true, Block's constructor
244 * will be requested to verify consistency of the encoded
245 * length in the Block, otherwise ignored
246 */
247 Block
248 block(bool verifyLength = true) const;
249
250private:
251 shared_ptr<Buffer> m_buffer;
252
253 // invariant: m_begin always points to the position of last-written byte (if prepending data)
254 iterator m_begin;
255 // invariant: m_end always points to the position of next unwritten byte (if appending data)
256 iterator m_end;
257};
258
259
260inline size_t
261Encoder::size() const
262{
263 return m_end - m_begin;
264}
265
266inline shared_ptr<Buffer>
267Encoder::getBuffer()
268{
269 return m_buffer;
270}
271
272inline size_t
273Encoder::capacity() const
274{
275 return m_buffer->size();
276}
277
278inline Buffer::iterator
279Encoder::begin()
280{
281 return m_begin;
282}
283
284inline Buffer::iterator
285Encoder::end()
286{
287 return m_end;
288}
289
290inline Buffer::const_iterator
291Encoder::begin() const
292{
293 return m_begin;
294}
295
296inline Buffer::const_iterator
297Encoder::end() const
298{
299 return m_end;
300}
301
302inline uint8_t*
303Encoder::buf()
304{
305 return &(*m_begin);
306}
307
308inline const uint8_t*
309Encoder::buf() const
310{
311 return &(*m_begin);
312}
313
314template<class Iterator>
315inline size_t
316Encoder::prependRange(Iterator first, Iterator last)
317{
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000318 using ValueType = typename std::iterator_traits<Iterator>::value_type;
319 static_assert(sizeof(ValueType) == 1 && !std::is_same<ValueType, bool>::value, "");
320
Alexander Afanasyev74633892015-02-08 18:08:46 -0800321 size_t length = std::distance(first, last);
322 reserveFront(length);
323
324 m_begin -= length;
325 std::copy(first, last, m_begin);
326 return length;
327}
328
329
330template<class Iterator>
331inline size_t
332Encoder::appendRange(Iterator first, Iterator last)
333{
Junxiao Shi5c9ee282017-08-13 17:06:09 +0000334 using ValueType = typename std::iterator_traits<Iterator>::value_type;
335 static_assert(sizeof(ValueType) == 1 && !std::is_same<ValueType, bool>::value, "");
336
Alexander Afanasyev74633892015-02-08 18:08:46 -0800337 size_t length = std::distance(first, last);
338 reserveBack(length);
339
340 std::copy(first, last, m_end);
341 m_end += length;
342 return length;
343}
344
345
346} // namespace encoding
347} // namespace ndn
348
349#endif // NDN_ENCODING_ENCODER_HPP