blob: eac26f991c6a2f2bba78c717f4c4539304e59b54 [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"
21
22#include <boost/lexical_cast.hpp>
23
24namespace ndn {
25
Alexander Afanasyev217325b2014-02-06 15:03:28 -080026namespace encoding {
27const bool Buffer = true;
28const bool Estimator = false;
29} // encoding
30
31template<bool isRealEncoderNotEstimator>
32class EncodingImpl;
33
34typedef EncodingImpl<encoding::Buffer> EncodingBuffer;
35typedef EncodingImpl<encoding::Estimator> EncodingEstimator;
36
Wentao Shang77949212014-02-01 23:42:24 -080037/**
38 * @brief Class representing wire element of the NDN packet
39 */
Alexander Afanasyev217325b2014-02-06 15:03:28 -080040template<>
41class EncodingImpl<encoding::Buffer>
Wentao Shang77949212014-02-01 23:42:24 -080042{
43public:
Wentao Shang77949212014-02-01 23:42:24 -080044 /**
Alexander Afanasyev217325b2014-02-06 15:03:28 -080045 * @brief Constructor to create a EncodingImpl with specified reserved sizes
46 *
47 * The caller should make sure that that reserveFromBack does not exceed totalReserve,
48 * otherwise behavior is undefined.
Wentao Shang77949212014-02-01 23:42:24 -080049 */
Alexander Afanasyev217325b2014-02-06 15:03:28 -080050 EncodingImpl (size_t totalReserve = 8800,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080051 size_t reserveFromBack = 400)
Alexander Afanasyev217325b2014-02-06 15:03:28 -080052 : m_buffer (new Buffer (totalReserve))
Wentao Shang77949212014-02-01 23:42:24 -080053 {
Alexander Afanasyev217325b2014-02-06 15:03:28 -080054 m_begin = m_end = m_buffer->end () - (reserveFromBack < totalReserve ? reserveFromBack : 0);
Wentao Shang77949212014-02-01 23:42:24 -080055 }
56
57 inline size_t
58 size () const;
59
60 inline size_t
61 capacity () const;
62
63 inline uint8_t*
64 buf ();
65
66 inline const uint8_t*
67 buf () const;
68
Alexander Afanasyev187bc482014-02-06 15:04:04 -080069 inline Block
70 block () const;
71
Wentao Shang77949212014-02-01 23:42:24 -080072 inline void
73 resize (size_t sz, bool addInFront);
74
75 inline Buffer::iterator
76 begin ();
77
78 inline Buffer::iterator
79 end ();
80
81 inline Buffer::const_iterator
82 begin () const;
83
84 inline Buffer::const_iterator
85 end () const;
86
87 inline size_t
88 prependByte (uint8_t val);
89
90 inline size_t
91 prependByteArray (const uint8_t *arr, size_t len);
92
93 inline size_t
94 prependBuffer (const Buffer& arr);
95
96 inline size_t
97 prependNonNegativeInteger (uint64_t varNumber);
98
99 inline size_t
100 prependVarNumber (uint64_t varNumber);
101
102 inline size_t
103 appendByte (uint8_t val);
104
105 inline size_t
106 appendByteArray (const uint8_t *arr, size_t len);
107
108 inline size_t
109 appendBuffer (const Buffer& arr);
110
111 inline size_t
112 appendNonNegativeInteger (uint64_t varNumber);
113
114 inline size_t
115 appendVarNumber (uint64_t varNumber);
116
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800117 // inline void
118 // removeByteFromFront ();
119
120 // inline void
121 // removeByteFromEnd ();
122
123 // inline void
124 // removeVarNumberFromFront (uint64_t varNumber);
125
126 // inline void
127 // removeVarNumberFromBack (uint64_t varNumber);
128
Wentao Shang77949212014-02-01 23:42:24 -0800129private:
130 BufferPtr m_buffer;
131
132 // invariant: m_begin always points to the position of last-written byte (if prepending data)
133 Buffer::iterator m_begin;
134 // invariant: m_end always points to the position of next unwritten byte (if appending data)
135 Buffer::iterator m_end;
136};
137
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800138
139/**
140 * @brief Class representing wire element of the NDN packet
141 */
142template<>
143class EncodingImpl<encoding::Estimator>
144{
145public:
146 EncodingImpl (size_t totalReserve = 8800,
147 size_t reserveFromBack = 400)
148 {
149 }
150
151 inline size_t
152 size () const;
153
154 inline size_t
155 prependByte (uint8_t val);
156
157 inline size_t
158 prependByteArray (const uint8_t *arr, size_t len);
159
160 inline size_t
161 prependBuffer (const Buffer& arr);
162
163 inline size_t
164 prependNonNegativeInteger (uint64_t varNumber);
165
166 inline size_t
167 prependVarNumber (uint64_t varNumber);
168
169 inline size_t
170 appendByte (uint8_t val);
171
172 inline size_t
173 appendByteArray (const uint8_t *arr, size_t len);
174
175 inline size_t
176 appendBuffer (const Buffer& arr);
177
178 inline size_t
179 appendNonNegativeInteger (uint64_t varNumber);
180
181 inline size_t
182 appendVarNumber (uint64_t varNumber);
183
184private:
185 size_t m_size;
186};
187
188
Wentao Shang77949212014-02-01 23:42:24 -0800189////////////////////////////////////////////////////////////////////////////////
190////////////////////////////////////////////////////////////////////////////////
191////////////////////////////////////////////////////////////////////////////////
192
193inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800194EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800195{
196 return m_end - m_begin;
197}
198
199inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800200EncodingImpl<encoding::Estimator>::size () const
201{
202 return m_size;
203}
204
205inline size_t
206EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800207{
208 return m_buffer->size ();
209}
210
211inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800212EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800213{
214 return &(*m_begin);
215}
216
217inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800218EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800219{
220 return &(*m_begin);
221}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800222
223inline Block
224EncodingImpl<encoding::Buffer>::block () const
225{
226 return Block(m_buffer,
227 m_begin, m_end);
228}
229
Wentao Shang77949212014-02-01 23:42:24 -0800230inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800231EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800232{
233 if (addInFront)
234 {
235 size_t diff_end = m_buffer->end () - m_end;
236 size_t diff_begin = m_buffer->end () - m_begin;
237
238 Buffer* buf = new Buffer (sz);
239 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
240
241 m_buffer.reset (buf);
242
243 m_end = m_buffer->end () - diff_end;
244 m_begin = m_buffer->end () - diff_begin;
245 }
246 else
247 {
248 size_t diff_end = m_end - m_buffer->begin ();
249 size_t diff_begin = m_begin - m_buffer->begin ();
250
251 Buffer* buf = new Buffer (sz);
252 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
253
254 m_buffer.reset (buf);
255
256 m_end = m_buffer->begin () + diff_end;
257 m_begin = m_buffer->begin () + diff_begin;
258 }
259}
260
261inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800262EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800263{
264 return m_begin;
265}
266
267inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800268EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800269{
270 return m_end;
271}
272
273inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800274EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800275{
276 return m_begin;
277}
278
279inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800280EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800281{
282 return m_end;
283}
284
285
286//////////////////////////////////////////////////////////
287// Prepend to the back of the buffer. Resize if needed. //
288//////////////////////////////////////////////////////////
289
290inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800291EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800292{
293 if (m_begin == m_buffer->begin ())
294 resize (m_buffer->size () * 2, true);
295
296 m_begin--;
297 *m_begin = val;
298 return 1;
299}
300
301inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800302EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
303{
304 m_size += 1;
305 return 1;
306}
307
308inline size_t
309EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800310{
311 if ((m_buffer->begin () + len) > m_begin)
312 resize (m_buffer->size () * 2 + len, true);
313
314 m_begin -= len;
315 std::copy (arr, arr + len, m_begin);
316 return len;
317}
318
319inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800320EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
321{
322 m_size += len;
323 return len;
324}
325
326inline size_t
327EncodingImpl<encoding::Buffer>::prependBuffer (const Buffer& arr)
Wentao Shang77949212014-02-01 23:42:24 -0800328{
329 if ((m_buffer->begin () + arr.size ()) > m_begin)
330 resize (m_buffer->size () * 2 + arr.size (), true);
331
332 m_begin -= arr.size ();
333 std::copy (arr.begin (), arr.end (), m_begin);
334 return arr.size ();
335}
336
337inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800338EncodingImpl<encoding::Estimator>::prependBuffer (const Buffer& arr)
339{
340 m_size += arr.size ();
341 return arr.size ();
342}
343
344inline size_t
345EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800346{
347 if (varNumber < 253) {
348 return prependByte (static_cast<uint8_t> (varNumber));
349 }
350 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
351 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
352 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
353 }
354 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
355 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
356 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
357 }
358 else {
359 uint64_t value = htobe64 (varNumber);
360 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
361 }
362}
363
364inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800365EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
366{
367 if (varNumber < 253) {
368 m_size += 1;
369 return 1;
370 }
371 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
372 m_size += 2;
373 return 2;
374 }
375 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
376 m_size += 4;
377 return 4;
378 }
379 else {
380 m_size += 8;
381 return 8;
382 }
383}
384
385inline size_t
386EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800387{
388 if (varNumber < 253) {
389 prependByte (static_cast<uint8_t> (varNumber));
390 return 1;
391 }
392 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
393 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
394 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
395 prependByte (253);
396 return 3;
397 }
398 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
399 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
400 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
401 prependByte (254);
402 return 5;
403 }
404 else {
405 uint64_t value = htobe64 (varNumber);
406 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
407 prependByte (255);
408 return 9;
409 }
410}
411
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800412inline size_t
413EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
414{
415 if (varNumber < 253) {
416 m_size += 1;
417 return 1;
418 }
419 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
420 m_size += 3;
421 return 3;
422 }
423 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
424 m_size += 5;
425 return 5;
426 }
427 else {
428 m_size += 9;
429 return 9;
430 }
431}
432
Wentao Shang77949212014-02-01 23:42:24 -0800433/////////////////////////////////////////////////////////
434// Append to the back of the buffer. Resize if needed. //
435/////////////////////////////////////////////////////////
436
437inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800438EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800439{
440 if (m_end == m_buffer->end ())
441 resize (m_buffer->size () * 2, false);
442
443 *m_end = val;
444 m_end++;
445 return 1;
446}
447
448inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800449EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
450{
451 return 1;
452}
453
454inline size_t
455EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800456{
457 if ((m_end + len) > m_buffer->end ())
458 resize (m_buffer->size () * 2 + len, false);
459
460 std::copy (arr, arr + len, m_end);
461 m_end += len;
462 return len;
463}
464
465inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800466EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
467{
468 return prependByteArray(arr, len);
469}
470
471inline size_t
472EncodingImpl<encoding::Buffer>::appendBuffer (const Buffer& arr)
Wentao Shang77949212014-02-01 23:42:24 -0800473{
474 if ((m_end + arr.size ()) > m_buffer->end ())
475 resize (m_buffer->size () * 2 + arr.size (), false);
476
477 std::copy (arr.begin (), arr.end (), m_end);
478 m_end -= arr.size ();
479 return arr.size ();
480}
481
482inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800483EncodingImpl<encoding::Estimator>::appendBuffer (const Buffer& arr)
484{
485 return prependBuffer(arr);
486}
487
488inline size_t
489EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800490{
491 if (varNumber < 253) {
492 return appendByte (static_cast<uint8_t> (varNumber));
493 }
494 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
495 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
496 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
497 }
498 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
499 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
500 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
501 }
502 else {
503 uint64_t value = htobe64 (varNumber);
504 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
505 }
506}
507
508inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800509EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
510{
511 return prependNonNegativeInteger(varNumber);
512}
513
514inline size_t
515EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800516{
517 if (varNumber < 253) {
518 appendByte (static_cast<uint8_t> (varNumber));
519 return 1;
520 }
521 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
522 appendByte (253);
523 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
524 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
525 return 3;
526 }
527 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
528 appendByte (254);
529 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
530 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
531 return 5;
532 }
533 else {
534 appendByte (255);
535 uint64_t value = htobe64 (varNumber);
536 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
537 return 9;
538 }
539}
540
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800541inline size_t
542EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
543{
544 return prependVarNumber(varNumber);
545}
546
Wentao Shang77949212014-02-01 23:42:24 -0800547} // ndn
548
549#endif // NDN_ENCODING_BUFFER_HPP