blob: b4c9018a854fbf7f83519b167f9a13bf3f0b6f60 [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
58 inline size_t
59 size () const;
60
61 inline size_t
62 capacity () const;
63
64 inline uint8_t*
65 buf ();
66
67 inline const uint8_t*
68 buf () const;
69
Alexander Afanasyev187bc482014-02-06 15:04:04 -080070 inline Block
71 block () const;
72
Wentao Shang77949212014-02-01 23:42:24 -080073 inline void
74 resize (size_t sz, bool addInFront);
75
76 inline Buffer::iterator
77 begin ();
78
79 inline Buffer::iterator
80 end ();
81
82 inline Buffer::const_iterator
83 begin () const;
84
85 inline Buffer::const_iterator
86 end () const;
87
88 inline size_t
89 prependByte (uint8_t val);
90
91 inline size_t
92 prependByteArray (const uint8_t *arr, size_t len);
93
94 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -080095 prependNonNegativeInteger (uint64_t varNumber);
96
97 inline size_t
98 prependVarNumber (uint64_t varNumber);
99
100 inline size_t
101 appendByte (uint8_t val);
102
103 inline size_t
104 appendByteArray (const uint8_t *arr, size_t len);
105
106 inline size_t
Wentao Shang77949212014-02-01 23:42:24 -0800107 appendNonNegativeInteger (uint64_t varNumber);
108
109 inline size_t
110 appendVarNumber (uint64_t varNumber);
111
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800112 // inline void
113 // removeByteFromFront ();
114
115 // inline void
116 // removeByteFromEnd ();
117
118 // inline void
119 // removeVarNumberFromFront (uint64_t varNumber);
120
121 // inline void
122 // removeVarNumberFromBack (uint64_t varNumber);
123
Wentao Shang77949212014-02-01 23:42:24 -0800124private:
125 BufferPtr m_buffer;
126
127 // invariant: m_begin always points to the position of last-written byte (if prepending data)
128 Buffer::iterator m_begin;
129 // invariant: m_end always points to the position of next unwritten byte (if appending data)
130 Buffer::iterator m_end;
131};
132
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800133
134/**
135 * @brief Class representing wire element of the NDN packet
136 */
137template<>
138class EncodingImpl<encoding::Estimator>
139{
140public:
141 EncodingImpl (size_t totalReserve = 8800,
142 size_t reserveFromBack = 400)
143 {
144 }
145
146 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800147 prependByte (uint8_t val);
148
149 inline size_t
150 prependByteArray (const uint8_t *arr, size_t len);
151
152 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800153 prependNonNegativeInteger (uint64_t varNumber);
154
155 inline size_t
156 prependVarNumber (uint64_t varNumber);
157
158 inline size_t
159 appendByte (uint8_t val);
160
161 inline size_t
162 appendByteArray (const uint8_t *arr, size_t len);
163
164 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800165 appendNonNegativeInteger (uint64_t varNumber);
166
167 inline size_t
168 appendVarNumber (uint64_t varNumber);
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800169};
170
171
Wentao Shang77949212014-02-01 23:42:24 -0800172////////////////////////////////////////////////////////////////////////////////
173////////////////////////////////////////////////////////////////////////////////
174////////////////////////////////////////////////////////////////////////////////
175
176inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800177EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800178{
179 return m_end - m_begin;
180}
181
182inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800183EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800184{
185 return m_buffer->size ();
186}
187
188inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800189EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800190{
191 return &(*m_begin);
192}
193
194inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800195EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800196{
197 return &(*m_begin);
198}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800199
200inline Block
201EncodingImpl<encoding::Buffer>::block () const
202{
203 return Block(m_buffer,
204 m_begin, m_end);
205}
206
Wentao Shang77949212014-02-01 23:42:24 -0800207inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800208EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800209{
210 if (addInFront)
211 {
212 size_t diff_end = m_buffer->end () - m_end;
213 size_t diff_begin = m_buffer->end () - m_begin;
214
215 Buffer* buf = new Buffer (sz);
216 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
217
218 m_buffer.reset (buf);
219
220 m_end = m_buffer->end () - diff_end;
221 m_begin = m_buffer->end () - diff_begin;
222 }
223 else
224 {
225 size_t diff_end = m_end - m_buffer->begin ();
226 size_t diff_begin = m_begin - m_buffer->begin ();
227
228 Buffer* buf = new Buffer (sz);
229 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
230
231 m_buffer.reset (buf);
232
233 m_end = m_buffer->begin () + diff_end;
234 m_begin = m_buffer->begin () + diff_begin;
235 }
236}
237
238inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800239EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800240{
241 return m_begin;
242}
243
244inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800245EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800246{
247 return m_end;
248}
249
250inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800251EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800252{
253 return m_begin;
254}
255
256inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800257EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800258{
259 return m_end;
260}
261
262
263//////////////////////////////////////////////////////////
264// Prepend to the back of the buffer. Resize if needed. //
265//////////////////////////////////////////////////////////
266
267inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800268EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800269{
270 if (m_begin == m_buffer->begin ())
271 resize (m_buffer->size () * 2, true);
272
273 m_begin--;
274 *m_begin = val;
275 return 1;
276}
277
278inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800279EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
280{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800281 return 1;
282}
283
284inline size_t
285EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800286{
287 if ((m_buffer->begin () + len) > m_begin)
288 resize (m_buffer->size () * 2 + len, true);
289
290 m_begin -= len;
291 std::copy (arr, arr + len, m_begin);
292 return len;
293}
294
295inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800296EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
297{
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800298 return len;
299}
300
301inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800302EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800303{
304 if (varNumber < 253) {
305 return prependByte (static_cast<uint8_t> (varNumber));
306 }
307 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
308 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
309 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
310 }
311 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
312 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
313 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
314 }
315 else {
316 uint64_t value = htobe64 (varNumber);
317 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
318 }
319}
320
321inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800322EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
323{
324 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800325 return 1;
326 }
327 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800328 return 2;
329 }
330 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800331 return 4;
332 }
333 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800334 return 8;
335 }
336}
337
338inline size_t
339EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800340{
341 if (varNumber < 253) {
342 prependByte (static_cast<uint8_t> (varNumber));
343 return 1;
344 }
345 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
346 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
347 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
348 prependByte (253);
349 return 3;
350 }
351 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
352 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
353 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
354 prependByte (254);
355 return 5;
356 }
357 else {
358 uint64_t value = htobe64 (varNumber);
359 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
360 prependByte (255);
361 return 9;
362 }
363}
364
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800365inline size_t
366EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
367{
368 if (varNumber < 253) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800369 return 1;
370 }
371 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800372 return 3;
373 }
374 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800375 return 5;
376 }
377 else {
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800378 return 9;
379 }
380}
381
Wentao Shang77949212014-02-01 23:42:24 -0800382/////////////////////////////////////////////////////////
383// Append to the back of the buffer. Resize if needed. //
384/////////////////////////////////////////////////////////
385
386inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800387EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800388{
389 if (m_end == m_buffer->end ())
390 resize (m_buffer->size () * 2, false);
391
392 *m_end = val;
393 m_end++;
394 return 1;
395}
396
397inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800398EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
399{
400 return 1;
401}
402
403inline size_t
404EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800405{
406 if ((m_end + len) > m_buffer->end ())
407 resize (m_buffer->size () * 2 + len, false);
408
409 std::copy (arr, arr + len, m_end);
410 m_end += len;
411 return len;
412}
413
414inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800415EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
416{
417 return prependByteArray(arr, len);
418}
419
420inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800421EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800422{
423 if (varNumber < 253) {
424 return appendByte (static_cast<uint8_t> (varNumber));
425 }
426 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
427 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
428 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
429 }
430 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
431 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
432 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
433 }
434 else {
435 uint64_t value = htobe64 (varNumber);
436 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
437 }
438}
439
440inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800441EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
442{
443 return prependNonNegativeInteger(varNumber);
444}
445
446inline size_t
447EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800448{
449 if (varNumber < 253) {
450 appendByte (static_cast<uint8_t> (varNumber));
451 return 1;
452 }
453 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
454 appendByte (253);
455 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
456 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
457 return 3;
458 }
459 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
460 appendByte (254);
461 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
462 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
463 return 5;
464 }
465 else {
466 appendByte (255);
467 uint64_t value = htobe64 (varNumber);
468 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
469 return 9;
470 }
471}
472
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800473inline size_t
474EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
475{
476 return prependVarNumber(varNumber);
477}
478
Wentao Shang77949212014-02-01 23:42:24 -0800479} // ndn
480
481#endif // NDN_ENCODING_BUFFER_HPP