blob: 62d6a12665198f7f7a6dfc9b9e901731de38aacb [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 {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080027static const bool Buffer = true;
28static const bool Estimator = false;
Alexander Afanasyev217325b2014-02-06 15:03:28 -080029} // 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
Wentao Shang77949212014-02-01 23:42:24 -080094 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
Wentao Shang77949212014-02-01 23:42:24 -0800106 appendNonNegativeInteger (uint64_t varNumber);
107
108 inline size_t
109 appendVarNumber (uint64_t varNumber);
110
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800111 // inline void
112 // removeByteFromFront ();
113
114 // inline void
115 // removeByteFromEnd ();
116
117 // inline void
118 // removeVarNumberFromFront (uint64_t varNumber);
119
120 // inline void
121 // removeVarNumberFromBack (uint64_t varNumber);
122
Wentao Shang77949212014-02-01 23:42:24 -0800123private:
124 BufferPtr m_buffer;
125
126 // invariant: m_begin always points to the position of last-written byte (if prepending data)
127 Buffer::iterator m_begin;
128 // invariant: m_end always points to the position of next unwritten byte (if appending data)
129 Buffer::iterator m_end;
130};
131
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800132
133/**
134 * @brief Class representing wire element of the NDN packet
135 */
136template<>
137class EncodingImpl<encoding::Estimator>
138{
139public:
140 EncodingImpl (size_t totalReserve = 8800,
141 size_t reserveFromBack = 400)
142 {
143 }
144
145 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800146 prependByte (uint8_t val);
147
148 inline size_t
149 prependByteArray (const uint8_t *arr, size_t len);
150
151 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800152 prependNonNegativeInteger (uint64_t varNumber);
153
154 inline size_t
155 prependVarNumber (uint64_t varNumber);
156
157 inline size_t
158 appendByte (uint8_t val);
159
160 inline size_t
161 appendByteArray (const uint8_t *arr, size_t len);
162
163 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800164 appendNonNegativeInteger (uint64_t varNumber);
165
166 inline size_t
167 appendVarNumber (uint64_t varNumber);
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800168};
169
170
Wentao Shang77949212014-02-01 23:42:24 -0800171////////////////////////////////////////////////////////////////////////////////
172////////////////////////////////////////////////////////////////////////////////
173////////////////////////////////////////////////////////////////////////////////
174
175inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800176EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800177{
178 return m_end - m_begin;
179}
180
181inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800182EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800183{
184 return m_buffer->size ();
185}
186
187inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800188EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800189{
190 return &(*m_begin);
191}
192
193inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800194EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800195{
196 return &(*m_begin);
197}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800198
199inline Block
200EncodingImpl<encoding::Buffer>::block () const
201{
202 return Block(m_buffer,
203 m_begin, m_end);
204}
205
Wentao Shang77949212014-02-01 23:42:24 -0800206inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800207EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800208{
209 if (addInFront)
210 {
211 size_t diff_end = m_buffer->end () - m_end;
212 size_t diff_begin = m_buffer->end () - m_begin;
213
214 Buffer* buf = new Buffer (sz);
215 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
216
217 m_buffer.reset (buf);
218
219 m_end = m_buffer->end () - diff_end;
220 m_begin = m_buffer->end () - diff_begin;
221 }
222 else
223 {
224 size_t diff_end = m_end - m_buffer->begin ();
225 size_t diff_begin = m_begin - m_buffer->begin ();
226
227 Buffer* buf = new Buffer (sz);
228 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
229
230 m_buffer.reset (buf);
231
232 m_end = m_buffer->begin () + diff_end;
233 m_begin = m_buffer->begin () + diff_begin;
234 }
235}
236
237inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800238EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800239{
240 return m_begin;
241}
242
243inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800244EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800245{
246 return m_end;
247}
248
249inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800250EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800251{
252 return m_begin;
253}
254
255inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800256EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800257{
258 return m_end;
259}
260
261
262//////////////////////////////////////////////////////////
263// Prepend to the back of the buffer. Resize if needed. //
264//////////////////////////////////////////////////////////
265
266inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800267EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800268{
269 if (m_begin == m_buffer->begin ())
270 resize (m_buffer->size () * 2, true);
271
272 m_begin--;
273 *m_begin = val;
274 return 1;
275}
276
277inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800278EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
279{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800280 return 1;
281}
282
283inline size_t
284EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800285{
286 if ((m_buffer->begin () + len) > m_begin)
287 resize (m_buffer->size () * 2 + len, true);
288
289 m_begin -= len;
290 std::copy (arr, arr + len, m_begin);
291 return len;
292}
293
294inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800295EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
296{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800297 return len;
298}
299
300inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800301EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800302{
303 if (varNumber < 253) {
304 return prependByte (static_cast<uint8_t> (varNumber));
305 }
306 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
307 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
308 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
309 }
310 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
311 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
312 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
313 }
314 else {
315 uint64_t value = htobe64 (varNumber);
316 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
317 }
318}
319
320inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800321EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
322{
323 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800324 return 1;
325 }
326 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800327 return 2;
328 }
329 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800330 return 4;
331 }
332 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800333 return 8;
334 }
335}
336
337inline size_t
338EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800339{
340 if (varNumber < 253) {
341 prependByte (static_cast<uint8_t> (varNumber));
342 return 1;
343 }
344 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
345 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
346 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
347 prependByte (253);
348 return 3;
349 }
350 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
351 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
352 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
353 prependByte (254);
354 return 5;
355 }
356 else {
357 uint64_t value = htobe64 (varNumber);
358 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
359 prependByte (255);
360 return 9;
361 }
362}
363
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800364inline size_t
365EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
366{
367 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800368 return 1;
369 }
370 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800371 return 3;
372 }
373 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800374 return 5;
375 }
376 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800377 return 9;
378 }
379}
380
Wentao Shang77949212014-02-01 23:42:24 -0800381/////////////////////////////////////////////////////////
382// Append to the back of the buffer. Resize if needed. //
383/////////////////////////////////////////////////////////
384
385inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800386EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800387{
388 if (m_end == m_buffer->end ())
389 resize (m_buffer->size () * 2, false);
390
391 *m_end = val;
392 m_end++;
393 return 1;
394}
395
396inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800397EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
398{
399 return 1;
400}
401
402inline size_t
403EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800404{
405 if ((m_end + len) > m_buffer->end ())
406 resize (m_buffer->size () * 2 + len, false);
407
408 std::copy (arr, arr + len, m_end);
409 m_end += len;
410 return len;
411}
412
413inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800414EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
415{
416 return prependByteArray(arr, len);
417}
418
419inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800420EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800421{
422 if (varNumber < 253) {
423 return appendByte (static_cast<uint8_t> (varNumber));
424 }
425 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
426 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
427 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
428 }
429 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
430 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
431 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
432 }
433 else {
434 uint64_t value = htobe64 (varNumber);
435 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
436 }
437}
438
439inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800440EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
441{
442 return prependNonNegativeInteger(varNumber);
443}
444
445inline size_t
446EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800447{
448 if (varNumber < 253) {
449 appendByte (static_cast<uint8_t> (varNumber));
450 return 1;
451 }
452 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
453 appendByte (253);
454 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
455 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
456 return 3;
457 }
458 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
459 appendByte (254);
460 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
461 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
462 return 5;
463 }
464 else {
465 appendByte (255);
466 uint64_t value = htobe64 (varNumber);
467 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
468 return 9;
469 }
470}
471
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800472inline size_t
473EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
474{
475 return prependVarNumber(varNumber);
476}
477
Wentao Shang77949212014-02-01 23:42:24 -0800478} // ndn
479
480#endif // NDN_ENCODING_BUFFER_HPP