blob: 8bf6d2c6b42dc03f800828df51f652dbebf5f7e2 [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,
51 size_t reserveFromBack = 400)
52 : 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
69 inline void
70 resize (size_t sz, bool addInFront);
71
72 inline Buffer::iterator
73 begin ();
74
75 inline Buffer::iterator
76 end ();
77
78 inline Buffer::const_iterator
79 begin () const;
80
81 inline Buffer::const_iterator
82 end () const;
83
84 inline size_t
85 prependByte (uint8_t val);
86
87 inline size_t
88 prependByteArray (const uint8_t *arr, size_t len);
89
90 inline size_t
91 prependBuffer (const Buffer& arr);
92
93 inline size_t
94 prependNonNegativeInteger (uint64_t varNumber);
95
96 inline size_t
97 prependVarNumber (uint64_t varNumber);
98
99 inline size_t
100 appendByte (uint8_t val);
101
102 inline size_t
103 appendByteArray (const uint8_t *arr, size_t len);
104
105 inline size_t
106 appendBuffer (const Buffer& arr);
107
108 inline size_t
109 appendNonNegativeInteger (uint64_t varNumber);
110
111 inline size_t
112 appendVarNumber (uint64_t varNumber);
113
114private:
115 BufferPtr m_buffer;
116
117 // invariant: m_begin always points to the position of last-written byte (if prepending data)
118 Buffer::iterator m_begin;
119 // invariant: m_end always points to the position of next unwritten byte (if appending data)
120 Buffer::iterator m_end;
121};
122
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800123
124/**
125 * @brief Class representing wire element of the NDN packet
126 */
127template<>
128class EncodingImpl<encoding::Estimator>
129{
130public:
131 EncodingImpl (size_t totalReserve = 8800,
132 size_t reserveFromBack = 400)
133 {
134 }
135
136 inline size_t
137 size () const;
138
139 inline size_t
140 prependByte (uint8_t val);
141
142 inline size_t
143 prependByteArray (const uint8_t *arr, size_t len);
144
145 inline size_t
146 prependBuffer (const Buffer& arr);
147
148 inline size_t
149 prependNonNegativeInteger (uint64_t varNumber);
150
151 inline size_t
152 prependVarNumber (uint64_t varNumber);
153
154 inline size_t
155 appendByte (uint8_t val);
156
157 inline size_t
158 appendByteArray (const uint8_t *arr, size_t len);
159
160 inline size_t
161 appendBuffer (const Buffer& arr);
162
163 inline size_t
164 appendNonNegativeInteger (uint64_t varNumber);
165
166 inline size_t
167 appendVarNumber (uint64_t varNumber);
168
169private:
170 size_t m_size;
171};
172
173
Wentao Shang77949212014-02-01 23:42:24 -0800174////////////////////////////////////////////////////////////////////////////////
175////////////////////////////////////////////////////////////////////////////////
176////////////////////////////////////////////////////////////////////////////////
177
178inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800179EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800180{
181 return m_end - m_begin;
182}
183
184inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800185EncodingImpl<encoding::Estimator>::size () const
186{
187 return m_size;
188}
189
190inline size_t
191EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800192{
193 return m_buffer->size ();
194}
195
196inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800197EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800198{
199 return &(*m_begin);
200}
201
202inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800203EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800204{
205 return &(*m_begin);
206}
207
208inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800209EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800210{
211 if (addInFront)
212 {
213 size_t diff_end = m_buffer->end () - m_end;
214 size_t diff_begin = m_buffer->end () - m_begin;
215
216 Buffer* buf = new Buffer (sz);
217 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
218
219 m_buffer.reset (buf);
220
221 m_end = m_buffer->end () - diff_end;
222 m_begin = m_buffer->end () - diff_begin;
223 }
224 else
225 {
226 size_t diff_end = m_end - m_buffer->begin ();
227 size_t diff_begin = m_begin - m_buffer->begin ();
228
229 Buffer* buf = new Buffer (sz);
230 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
231
232 m_buffer.reset (buf);
233
234 m_end = m_buffer->begin () + diff_end;
235 m_begin = m_buffer->begin () + diff_begin;
236 }
237}
238
239inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800240EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800241{
242 return m_begin;
243}
244
245inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800246EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800247{
248 return m_end;
249}
250
251inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800252EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800253{
254 return m_begin;
255}
256
257inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800258EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800259{
260 return m_end;
261}
262
263
264//////////////////////////////////////////////////////////
265// Prepend to the back of the buffer. Resize if needed. //
266//////////////////////////////////////////////////////////
267
268inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800269EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800270{
271 if (m_begin == m_buffer->begin ())
272 resize (m_buffer->size () * 2, true);
273
274 m_begin--;
275 *m_begin = val;
276 return 1;
277}
278
279inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800280EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
281{
282 m_size += 1;
283 return 1;
284}
285
286inline size_t
287EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800288{
289 if ((m_buffer->begin () + len) > m_begin)
290 resize (m_buffer->size () * 2 + len, true);
291
292 m_begin -= len;
293 std::copy (arr, arr + len, m_begin);
294 return len;
295}
296
297inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800298EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
299{
300 m_size += len;
301 return len;
302}
303
304inline size_t
305EncodingImpl<encoding::Buffer>::prependBuffer (const Buffer& arr)
Wentao Shang77949212014-02-01 23:42:24 -0800306{
307 if ((m_buffer->begin () + arr.size ()) > m_begin)
308 resize (m_buffer->size () * 2 + arr.size (), true);
309
310 m_begin -= arr.size ();
311 std::copy (arr.begin (), arr.end (), m_begin);
312 return arr.size ();
313}
314
315inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800316EncodingImpl<encoding::Estimator>::prependBuffer (const Buffer& arr)
317{
318 m_size += arr.size ();
319 return arr.size ();
320}
321
322inline size_t
323EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800324{
325 if (varNumber < 253) {
326 return prependByte (static_cast<uint8_t> (varNumber));
327 }
328 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
329 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
330 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
331 }
332 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
333 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
334 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
335 }
336 else {
337 uint64_t value = htobe64 (varNumber);
338 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
339 }
340}
341
342inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800343EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
344{
345 if (varNumber < 253) {
346 m_size += 1;
347 return 1;
348 }
349 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
350 m_size += 2;
351 return 2;
352 }
353 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
354 m_size += 4;
355 return 4;
356 }
357 else {
358 m_size += 8;
359 return 8;
360 }
361}
362
363inline size_t
364EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800365{
366 if (varNumber < 253) {
367 prependByte (static_cast<uint8_t> (varNumber));
368 return 1;
369 }
370 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
371 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
372 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
373 prependByte (253);
374 return 3;
375 }
376 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
377 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
378 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
379 prependByte (254);
380 return 5;
381 }
382 else {
383 uint64_t value = htobe64 (varNumber);
384 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
385 prependByte (255);
386 return 9;
387 }
388}
389
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800390inline size_t
391EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
392{
393 if (varNumber < 253) {
394 m_size += 1;
395 return 1;
396 }
397 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
398 m_size += 3;
399 return 3;
400 }
401 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
402 m_size += 5;
403 return 5;
404 }
405 else {
406 m_size += 9;
407 return 9;
408 }
409}
410
Wentao Shang77949212014-02-01 23:42:24 -0800411/////////////////////////////////////////////////////////
412// Append to the back of the buffer. Resize if needed. //
413/////////////////////////////////////////////////////////
414
415inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800416EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800417{
418 if (m_end == m_buffer->end ())
419 resize (m_buffer->size () * 2, false);
420
421 *m_end = val;
422 m_end++;
423 return 1;
424}
425
426inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800427EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
428{
429 return 1;
430}
431
432inline size_t
433EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800434{
435 if ((m_end + len) > m_buffer->end ())
436 resize (m_buffer->size () * 2 + len, false);
437
438 std::copy (arr, arr + len, m_end);
439 m_end += len;
440 return len;
441}
442
443inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800444EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
445{
446 return prependByteArray(arr, len);
447}
448
449inline size_t
450EncodingImpl<encoding::Buffer>::appendBuffer (const Buffer& arr)
Wentao Shang77949212014-02-01 23:42:24 -0800451{
452 if ((m_end + arr.size ()) > m_buffer->end ())
453 resize (m_buffer->size () * 2 + arr.size (), false);
454
455 std::copy (arr.begin (), arr.end (), m_end);
456 m_end -= arr.size ();
457 return arr.size ();
458}
459
460inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800461EncodingImpl<encoding::Estimator>::appendBuffer (const Buffer& arr)
462{
463 return prependBuffer(arr);
464}
465
466inline size_t
467EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800468{
469 if (varNumber < 253) {
470 return appendByte (static_cast<uint8_t> (varNumber));
471 }
472 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
473 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
474 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
475 }
476 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
477 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
478 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
479 }
480 else {
481 uint64_t value = htobe64 (varNumber);
482 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
483 }
484}
485
486inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800487EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
488{
489 return prependNonNegativeInteger(varNumber);
490}
491
492inline size_t
493EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800494{
495 if (varNumber < 253) {
496 appendByte (static_cast<uint8_t> (varNumber));
497 return 1;
498 }
499 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
500 appendByte (253);
501 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
502 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
503 return 3;
504 }
505 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
506 appendByte (254);
507 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
508 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
509 return 5;
510 }
511 else {
512 appendByte (255);
513 uint64_t value = htobe64 (varNumber);
514 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
515 return 9;
516 }
517}
518
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800519inline size_t
520EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
521{
522 return prependVarNumber(varNumber);
523}
524
Wentao Shang77949212014-02-01 23:42:24 -0800525} // ndn
526
527#endif // NDN_ENCODING_BUFFER_HPP