blob: 4251fa96bfd15af4c078b0c1a03302f3e16e128a [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 Afanasyev5964fb72014-02-18 12:42:45 -080088 /**
89 * @brief Create Block from the underlying EncodingBuffer
90 *
91 * @param verifyLength If this parameter set to true, Block's constructor
92 * will be requested to verify consistency of the encoded
93 * length in the Block, otherwise ignored
94 */
Alexander Afanasyev187bc482014-02-06 15:04:04 -080095 inline Block
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080096 block (bool verifyLength = true) const;
Alexander Afanasyev187bc482014-02-06 15:04:04 -080097
Wentao Shang77949212014-02-01 23:42:24 -080098 inline void
99 resize (size_t sz, bool addInFront);
100
101 inline Buffer::iterator
102 begin ();
103
104 inline Buffer::iterator
105 end ();
106
107 inline Buffer::const_iterator
108 begin () const;
109
110 inline Buffer::const_iterator
111 end () const;
112
113 inline size_t
114 prependByte (uint8_t val);
115
116 inline size_t
117 prependByteArray (const uint8_t *arr, size_t len);
118
119 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -0800120 prependNonNegativeInteger (uint64_t varNumber);
121
122 inline size_t
123 prependVarNumber (uint64_t varNumber);
124
125 inline size_t
126 appendByte (uint8_t val);
127
128 inline size_t
129 appendByteArray (const uint8_t *arr, size_t len);
130
131 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -0800132 appendNonNegativeInteger (uint64_t varNumber);
133
134 inline size_t
135 appendVarNumber (uint64_t varNumber);
136
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800137 // inline void
138 // removeByteFromFront ();
139
140 // inline void
141 // removeByteFromEnd ();
142
143 // inline void
144 // removeVarNumberFromFront (uint64_t varNumber);
145
146 // inline void
147 // removeVarNumberFromBack (uint64_t varNumber);
148
Wentao Shang77949212014-02-01 23:42:24 -0800149private:
150 BufferPtr m_buffer;
151
152 // invariant: m_begin always points to the position of last-written byte (if prepending data)
153 Buffer::iterator m_begin;
154 // invariant: m_end always points to the position of next unwritten byte (if appending data)
155 Buffer::iterator m_end;
Alexander Afanasyev15151312014-02-16 00:53:51 -0800156
157 friend class Block;
Wentao Shang77949212014-02-01 23:42:24 -0800158};
159
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800160
161/**
162 * @brief Class representing wire element of the NDN packet
163 */
164template<>
165class EncodingImpl<encoding::Estimator>
166{
167public:
168 EncodingImpl (size_t totalReserve = 8800,
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -0800169 size_t reserveFromBack = 400)
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800170 {
171 }
172
173 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800174 prependByte (uint8_t val);
175
176 inline size_t
177 prependByteArray (const uint8_t *arr, size_t len);
178
179 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800180 prependNonNegativeInteger (uint64_t varNumber);
181
182 inline size_t
183 prependVarNumber (uint64_t varNumber);
184
185 inline size_t
186 appendByte (uint8_t val);
187
188 inline size_t
189 appendByteArray (const uint8_t *arr, size_t len);
190
191 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800192 appendNonNegativeInteger (uint64_t varNumber);
193
194 inline size_t
195 appendVarNumber (uint64_t varNumber);
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800196};
197
198
Wentao Shang77949212014-02-01 23:42:24 -0800199////////////////////////////////////////////////////////////////////////////////
200////////////////////////////////////////////////////////////////////////////////
201////////////////////////////////////////////////////////////////////////////////
202
203inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800204EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800205{
206 return m_end - m_begin;
207}
208
209inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800210EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800211{
212 return m_buffer->size ();
213}
214
215inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800216EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800217{
218 return &(*m_begin);
219}
220
221inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800222EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800223{
224 return &(*m_begin);
225}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800226
227inline Block
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800228EncodingImpl<encoding::Buffer>::block (bool verifyLength/* = true*/) const
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800229{
230 return Block(m_buffer,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800231 m_begin, m_end,
232 verifyLength);
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800233}
234
Wentao Shang77949212014-02-01 23:42:24 -0800235inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800236EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800237{
238 if (addInFront)
239 {
240 size_t diff_end = m_buffer->end () - m_end;
241 size_t diff_begin = m_buffer->end () - m_begin;
242
243 Buffer* buf = new Buffer (sz);
244 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
245
246 m_buffer.reset (buf);
247
248 m_end = m_buffer->end () - diff_end;
249 m_begin = m_buffer->end () - diff_begin;
250 }
251 else
252 {
253 size_t diff_end = m_end - m_buffer->begin ();
254 size_t diff_begin = m_begin - m_buffer->begin ();
255
256 Buffer* buf = new Buffer (sz);
257 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
258
259 m_buffer.reset (buf);
260
261 m_end = m_buffer->begin () + diff_end;
262 m_begin = m_buffer->begin () + diff_begin;
263 }
264}
265
266inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800267EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800268{
269 return m_begin;
270}
271
272inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800273EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800274{
275 return m_end;
276}
277
278inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800279EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800280{
281 return m_begin;
282}
283
284inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800285EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800286{
287 return m_end;
288}
289
290
291//////////////////////////////////////////////////////////
292// Prepend to the back of the buffer. Resize if needed. //
293//////////////////////////////////////////////////////////
294
295inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800296EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800297{
298 if (m_begin == m_buffer->begin ())
299 resize (m_buffer->size () * 2, true);
300
301 m_begin--;
302 *m_begin = val;
303 return 1;
304}
305
306inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800307EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
308{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800309 return 1;
310}
311
312inline size_t
313EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800314{
315 if ((m_buffer->begin () + len) > m_begin)
316 resize (m_buffer->size () * 2 + len, true);
317
318 m_begin -= len;
319 std::copy (arr, arr + len, m_begin);
320 return len;
321}
322
323inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800324EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
325{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800326 return len;
327}
328
329inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800330EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800331{
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -0800332 if (varNumber <= std::numeric_limits<uint8_t>::max()) {
Wentao Shang77949212014-02-01 23:42:24 -0800333 return prependByte (static_cast<uint8_t> (varNumber));
334 }
335 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
336 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
337 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
338 }
339 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
340 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
341 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
342 }
343 else {
344 uint64_t value = htobe64 (varNumber);
345 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
346 }
347}
348
349inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800350EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
351{
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -0800352 if (varNumber <= std::numeric_limits<uint8_t>::max()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800353 return 1;
354 }
355 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800356 return 2;
357 }
358 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800359 return 4;
360 }
361 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800362 return 8;
363 }
364}
365
366inline size_t
367EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800368{
369 if (varNumber < 253) {
370 prependByte (static_cast<uint8_t> (varNumber));
371 return 1;
372 }
373 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
374 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
375 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
376 prependByte (253);
377 return 3;
378 }
379 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
380 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
381 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
382 prependByte (254);
383 return 5;
384 }
385 else {
386 uint64_t value = htobe64 (varNumber);
387 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
388 prependByte (255);
389 return 9;
390 }
391}
392
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800393inline size_t
394EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
395{
396 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800397 return 1;
398 }
399 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800400 return 3;
401 }
402 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800403 return 5;
404 }
405 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800406 return 9;
407 }
408}
409
Wentao Shang77949212014-02-01 23:42:24 -0800410/////////////////////////////////////////////////////////
411// Append to the back of the buffer. Resize if needed. //
412/////////////////////////////////////////////////////////
413
414inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800415EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800416{
417 if (m_end == m_buffer->end ())
418 resize (m_buffer->size () * 2, false);
419
420 *m_end = val;
421 m_end++;
422 return 1;
423}
424
425inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800426EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
427{
428 return 1;
429}
430
431inline size_t
432EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800433{
434 if ((m_end + len) > m_buffer->end ())
435 resize (m_buffer->size () * 2 + len, false);
436
437 std::copy (arr, arr + len, m_end);
438 m_end += len;
439 return len;
440}
441
442inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800443EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
444{
445 return prependByteArray(arr, len);
446}
447
448inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800449EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800450{
Alexander Afanasyev2d0b4572014-02-24 16:02:12 -0800451 if (varNumber <= std::numeric_limits<uint8_t>::max ()) {
Wentao Shang77949212014-02-01 23:42:24 -0800452 return appendByte (static_cast<uint8_t> (varNumber));
453 }
454 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
455 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
456 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
457 }
458 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
459 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
460 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
461 }
462 else {
463 uint64_t value = htobe64 (varNumber);
464 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
465 }
466}
467
468inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800469EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
470{
471 return prependNonNegativeInteger(varNumber);
472}
473
474inline size_t
475EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800476{
477 if (varNumber < 253) {
478 appendByte (static_cast<uint8_t> (varNumber));
479 return 1;
480 }
481 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
482 appendByte (253);
483 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
484 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
485 return 3;
486 }
487 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
488 appendByte (254);
489 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
490 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
491 return 5;
492 }
493 else {
494 appendByte (255);
495 uint64_t value = htobe64 (varNumber);
496 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
497 return 9;
498 }
499}
500
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800501inline size_t
502EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
503{
504 return prependVarNumber(varNumber);
505}
506
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800507/// helper methods
508
509template<bool P>
510inline size_t
511prependNonNegativeIntegerBlock(EncodingImpl<P>& blk, uint32_t type, uint64_t number)
512{
513 size_t var_len = blk.prependNonNegativeInteger(number);
514 size_t total_len = var_len;
515 total_len += blk.prependVarNumber(var_len);
516 total_len += blk.prependVarNumber(type);
517
518 return total_len;
519}
520
521template<bool P>
522inline size_t
Alexander Afanasyev0553cd52014-02-18 02:34:45 -0800523prependByteArrayBlock(EncodingImpl<P>& blk, uint32_t type, const uint8_t* array, size_t arraySize)
524{
525 size_t var_len = blk.prependByteArray(array, arraySize);
526 size_t total_len = var_len;
527 total_len += blk.prependVarNumber(var_len);
528 total_len += blk.prependVarNumber(type);
529
530 return total_len;
531}
532
533template<bool P>
534inline size_t
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800535prependBooleanBlock(EncodingImpl<P>& blk, uint32_t type)
536{
537 size_t total_len = blk.prependVarNumber(0);
538 total_len += blk.prependVarNumber(type);
539
540 return total_len;
541}
542
543
544template<bool P, class U>
545inline size_t
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800546prependNestedBlock(EncodingImpl<P>& blk, uint32_t type, const U& nestedBlock)
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800547{
548 size_t var_len = nestedBlock.wireEncode(blk);
549 size_t total_len = var_len;
550 total_len += blk.prependVarNumber(var_len);
551 total_len += blk.prependVarNumber(type);
552
553 return total_len;
554}
555
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800556template<bool P>
557inline size_t
558prependBlock(EncodingImpl<P>& blk, const Block& block)
559{
560 return blk.prependByteArray(block.wire(), block.size());
561}
562
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800563
Wentao Shang77949212014-02-01 23:42:24 -0800564} // ndn
565
566#endif // NDN_ENCODING_BUFFER_HPP