blob: c9abd31091186ff0638614e4d801b44074f9420d [file] [log] [blame]
Wentao Shang77949212014-02-01 23:42:24 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 *
5 * BSD license, See the LICENSE file for more information
6 *
7 * Author: Wentao Shang <wentao@cs.ucla.edu>
8 */
9
10#ifndef NDN_ENCODING_BUFFER_HPP
11#define NDN_ENCODING_BUFFER_HPP
12
13#include "../common.hpp"
14
15#include <list>
16#include <exception>
17#include <algorithm>
18
19#include "buffer.hpp"
20#include "tlv.hpp"
Alexander Afanasyev233750e2014-02-16 00:50:07 -080021#include "block.hpp"
Wentao Shang77949212014-02-01 23:42:24 -080022
23#include <boost/lexical_cast.hpp>
24
25namespace ndn {
26
Alexander Afanasyev217325b2014-02-06 15:03:28 -080027namespace encoding {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080028static const bool Buffer = true;
29static const bool Estimator = false;
Alexander Afanasyev217325b2014-02-06 15:03:28 -080030} // encoding
31
32template<bool isRealEncoderNotEstimator>
33class EncodingImpl;
34
35typedef EncodingImpl<encoding::Buffer> EncodingBuffer;
36typedef EncodingImpl<encoding::Estimator> EncodingEstimator;
37
Wentao Shang77949212014-02-01 23:42:24 -080038/**
39 * @brief Class representing wire element of the NDN packet
40 */
Alexander Afanasyev217325b2014-02-06 15:03:28 -080041template<>
42class EncodingImpl<encoding::Buffer>
Wentao Shang77949212014-02-01 23:42:24 -080043{
44public:
Wentao Shang77949212014-02-01 23:42:24 -080045 /**
Alexander Afanasyev217325b2014-02-06 15:03:28 -080046 * @brief Constructor to create a EncodingImpl with specified reserved sizes
47 *
48 * The caller should make sure that that reserveFromBack does not exceed totalReserve,
49 * otherwise behavior is undefined.
Wentao Shang77949212014-02-01 23:42:24 -080050 */
Alexander Afanasyev217325b2014-02-06 15:03:28 -080051 EncodingImpl (size_t totalReserve = 8800,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080052 size_t reserveFromBack = 400)
Alexander Afanasyev217325b2014-02-06 15:03:28 -080053 : m_buffer (new Buffer (totalReserve))
Wentao Shang77949212014-02-01 23:42:24 -080054 {
Alexander Afanasyev217325b2014-02-06 15:03:28 -080055 m_begin = m_end = m_buffer->end () - (reserveFromBack < totalReserve ? reserveFromBack : 0);
Wentao Shang77949212014-02-01 23:42:24 -080056 }
57
Alexander Afanasyev15151312014-02-16 00:53:51 -080058 /**
59 * @brief Create EncodingBlock from existing block
60 *
61 * This is a dangerous constructor and should be used with caution.
62 * It will modify contents of the buffer that is used by block and may
63 * impact data in other blocks.
64 *
65 * The primary purpose for this method is to be used to extend Block
66 * after sign operation.
67 */
68 explicit
69 EncodingImpl (const Block& block)
70 : m_buffer(const_pointer_cast<Buffer>(block.m_buffer))
71 , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
72 , m_end(m_buffer->begin() + (block.end() - m_buffer->begin()))
73 {
74 }
75
Wentao Shang77949212014-02-01 23:42:24 -080076 inline size_t
77 size () const;
78
79 inline size_t
80 capacity () const;
81
82 inline uint8_t*
83 buf ();
84
85 inline const uint8_t*
86 buf () const;
87
Alexander Afanasyev187bc482014-02-06 15:04:04 -080088 inline Block
89 block () const;
90
Wentao Shang77949212014-02-01 23:42:24 -080091 inline void
92 resize (size_t sz, bool addInFront);
93
94 inline Buffer::iterator
95 begin ();
96
97 inline Buffer::iterator
98 end ();
99
100 inline Buffer::const_iterator
101 begin () const;
102
103 inline Buffer::const_iterator
104 end () const;
105
106 inline size_t
107 prependByte (uint8_t val);
108
109 inline size_t
110 prependByteArray (const uint8_t *arr, size_t len);
111
112 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -0800113 prependNonNegativeInteger (uint64_t varNumber);
114
115 inline size_t
116 prependVarNumber (uint64_t varNumber);
117
118 inline size_t
119 appendByte (uint8_t val);
120
121 inline size_t
122 appendByteArray (const uint8_t *arr, size_t len);
123
124 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -0800125 appendNonNegativeInteger (uint64_t varNumber);
126
127 inline size_t
128 appendVarNumber (uint64_t varNumber);
129
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800130 // inline void
131 // removeByteFromFront ();
132
133 // inline void
134 // removeByteFromEnd ();
135
136 // inline void
137 // removeVarNumberFromFront (uint64_t varNumber);
138
139 // inline void
140 // removeVarNumberFromBack (uint64_t varNumber);
141
Wentao Shang77949212014-02-01 23:42:24 -0800142private:
143 BufferPtr m_buffer;
144
145 // invariant: m_begin always points to the position of last-written byte (if prepending data)
146 Buffer::iterator m_begin;
147 // invariant: m_end always points to the position of next unwritten byte (if appending data)
148 Buffer::iterator m_end;
Alexander Afanasyev15151312014-02-16 00:53:51 -0800149
150 friend class Block;
Wentao Shang77949212014-02-01 23:42:24 -0800151};
152
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800153
154/**
155 * @brief Class representing wire element of the NDN packet
156 */
157template<>
158class EncodingImpl<encoding::Estimator>
159{
160public:
161 EncodingImpl (size_t totalReserve = 8800,
162 size_t reserveFromBack = 400)
163 {
164 }
165
166 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800167 prependByte (uint8_t val);
168
169 inline size_t
170 prependByteArray (const uint8_t *arr, size_t len);
171
172 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800173 prependNonNegativeInteger (uint64_t varNumber);
174
175 inline size_t
176 prependVarNumber (uint64_t varNumber);
177
178 inline size_t
179 appendByte (uint8_t val);
180
181 inline size_t
182 appendByteArray (const uint8_t *arr, size_t len);
183
184 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800185 appendNonNegativeInteger (uint64_t varNumber);
186
187 inline size_t
188 appendVarNumber (uint64_t varNumber);
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800189};
190
191
Wentao Shang77949212014-02-01 23:42:24 -0800192////////////////////////////////////////////////////////////////////////////////
193////////////////////////////////////////////////////////////////////////////////
194////////////////////////////////////////////////////////////////////////////////
195
196inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800197EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800198{
199 return m_end - m_begin;
200}
201
202inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800203EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800204{
205 return m_buffer->size ();
206}
207
208inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800209EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800210{
211 return &(*m_begin);
212}
213
214inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800215EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800216{
217 return &(*m_begin);
218}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800219
220inline Block
221EncodingImpl<encoding::Buffer>::block () const
222{
223 return Block(m_buffer,
224 m_begin, m_end);
225}
226
Wentao Shang77949212014-02-01 23:42:24 -0800227inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800228EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800229{
230 if (addInFront)
231 {
232 size_t diff_end = m_buffer->end () - m_end;
233 size_t diff_begin = m_buffer->end () - m_begin;
234
235 Buffer* buf = new Buffer (sz);
236 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
237
238 m_buffer.reset (buf);
239
240 m_end = m_buffer->end () - diff_end;
241 m_begin = m_buffer->end () - diff_begin;
242 }
243 else
244 {
245 size_t diff_end = m_end - m_buffer->begin ();
246 size_t diff_begin = m_begin - m_buffer->begin ();
247
248 Buffer* buf = new Buffer (sz);
249 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
250
251 m_buffer.reset (buf);
252
253 m_end = m_buffer->begin () + diff_end;
254 m_begin = m_buffer->begin () + diff_begin;
255 }
256}
257
258inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800259EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800260{
261 return m_begin;
262}
263
264inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800265EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800266{
267 return m_end;
268}
269
270inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800271EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800272{
273 return m_begin;
274}
275
276inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800277EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800278{
279 return m_end;
280}
281
282
283//////////////////////////////////////////////////////////
284// Prepend to the back of the buffer. Resize if needed. //
285//////////////////////////////////////////////////////////
286
287inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800288EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800289{
290 if (m_begin == m_buffer->begin ())
291 resize (m_buffer->size () * 2, true);
292
293 m_begin--;
294 *m_begin = val;
295 return 1;
296}
297
298inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800299EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
300{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800301 return 1;
302}
303
304inline size_t
305EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800306{
307 if ((m_buffer->begin () + len) > m_begin)
308 resize (m_buffer->size () * 2 + len, true);
309
310 m_begin -= len;
311 std::copy (arr, arr + len, m_begin);
312 return len;
313}
314
315inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800316EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
317{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800318 return len;
319}
320
321inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800322EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800323{
324 if (varNumber < 253) {
325 return prependByte (static_cast<uint8_t> (varNumber));
326 }
327 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
328 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
329 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
330 }
331 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
332 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
333 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
334 }
335 else {
336 uint64_t value = htobe64 (varNumber);
337 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
338 }
339}
340
341inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800342EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
343{
344 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800345 return 1;
346 }
347 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800348 return 2;
349 }
350 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800351 return 4;
352 }
353 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800354 return 8;
355 }
356}
357
358inline size_t
359EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800360{
361 if (varNumber < 253) {
362 prependByte (static_cast<uint8_t> (varNumber));
363 return 1;
364 }
365 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
366 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
367 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
368 prependByte (253);
369 return 3;
370 }
371 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
372 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
373 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
374 prependByte (254);
375 return 5;
376 }
377 else {
378 uint64_t value = htobe64 (varNumber);
379 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
380 prependByte (255);
381 return 9;
382 }
383}
384
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800385inline size_t
386EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
387{
388 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800389 return 1;
390 }
391 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800392 return 3;
393 }
394 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800395 return 5;
396 }
397 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800398 return 9;
399 }
400}
401
Wentao Shang77949212014-02-01 23:42:24 -0800402/////////////////////////////////////////////////////////
403// Append to the back of the buffer. Resize if needed. //
404/////////////////////////////////////////////////////////
405
406inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800407EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800408{
409 if (m_end == m_buffer->end ())
410 resize (m_buffer->size () * 2, false);
411
412 *m_end = val;
413 m_end++;
414 return 1;
415}
416
417inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800418EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
419{
420 return 1;
421}
422
423inline size_t
424EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800425{
426 if ((m_end + len) > m_buffer->end ())
427 resize (m_buffer->size () * 2 + len, false);
428
429 std::copy (arr, arr + len, m_end);
430 m_end += len;
431 return len;
432}
433
434inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800435EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
436{
437 return prependByteArray(arr, len);
438}
439
440inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800441EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800442{
443 if (varNumber < 253) {
444 return appendByte (static_cast<uint8_t> (varNumber));
445 }
446 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
447 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
448 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
449 }
450 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
451 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
452 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
453 }
454 else {
455 uint64_t value = htobe64 (varNumber);
456 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
457 }
458}
459
460inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800461EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
462{
463 return prependNonNegativeInteger(varNumber);
464}
465
466inline size_t
467EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800468{
469 if (varNumber < 253) {
470 appendByte (static_cast<uint8_t> (varNumber));
471 return 1;
472 }
473 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
474 appendByte (253);
475 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
476 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
477 return 3;
478 }
479 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
480 appendByte (254);
481 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
482 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
483 return 5;
484 }
485 else {
486 appendByte (255);
487 uint64_t value = htobe64 (varNumber);
488 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
489 return 9;
490 }
491}
492
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800493inline size_t
494EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
495{
496 return prependVarNumber(varNumber);
497}
498
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800499/// helper methods
500
501template<bool P>
502inline size_t
503prependNonNegativeIntegerBlock(EncodingImpl<P>& blk, uint32_t type, uint64_t number)
504{
505 size_t var_len = blk.prependNonNegativeInteger(number);
506 size_t total_len = var_len;
507 total_len += blk.prependVarNumber(var_len);
508 total_len += blk.prependVarNumber(type);
509
510 return total_len;
511}
512
513template<bool P>
514inline size_t
515prependBooleanBlock(EncodingImpl<P>& blk, uint32_t type)
516{
517 size_t total_len = blk.prependVarNumber(0);
518 total_len += blk.prependVarNumber(type);
519
520 return total_len;
521}
522
523
524template<bool P, class U>
525inline size_t
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800526prependNestedBlock(EncodingImpl<P>& blk, uint32_t type, const U& nestedBlock)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800527{
528 size_t var_len = nestedBlock.wireEncode(blk);
529 size_t total_len = var_len;
530 total_len += blk.prependVarNumber(var_len);
531 total_len += blk.prependVarNumber(type);
532
533 return total_len;
534}
535
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800536template<bool P>
537inline size_t
538prependBlock(EncodingImpl<P>& blk, const Block& block)
539{
540 return blk.prependByteArray(block.wire(), block.size());
541}
542
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800543
Wentao Shang77949212014-02-01 23:42:24 -0800544} // ndn
545
546#endif // NDN_ENCODING_BUFFER_HPP