blob: 8870941adca7625847f194a2a5de4b618bb1b257 [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
146 size () const;
147
148 inline size_t
149 prependByte (uint8_t val);
150
151 inline size_t
152 prependByteArray (const uint8_t *arr, size_t len);
153
154 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800155 prependNonNegativeInteger (uint64_t varNumber);
156
157 inline size_t
158 prependVarNumber (uint64_t varNumber);
159
160 inline size_t
161 appendByte (uint8_t val);
162
163 inline size_t
164 appendByteArray (const uint8_t *arr, size_t len);
165
166 inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800167 appendNonNegativeInteger (uint64_t varNumber);
168
169 inline size_t
170 appendVarNumber (uint64_t varNumber);
171
172private:
173 size_t m_size;
174};
175
176
Wentao Shang77949212014-02-01 23:42:24 -0800177////////////////////////////////////////////////////////////////////////////////
178////////////////////////////////////////////////////////////////////////////////
179////////////////////////////////////////////////////////////////////////////////
180
181inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800182EncodingImpl<encoding::Buffer>::size () const
Wentao Shang77949212014-02-01 23:42:24 -0800183{
184 return m_end - m_begin;
185}
186
187inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800188EncodingImpl<encoding::Estimator>::size () const
189{
190 return m_size;
191}
192
193inline size_t
194EncodingImpl<encoding::Buffer>::capacity () const
Wentao Shang77949212014-02-01 23:42:24 -0800195{
196 return m_buffer->size ();
197}
198
199inline uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800200EncodingImpl<encoding::Buffer>::buf ()
Wentao Shang77949212014-02-01 23:42:24 -0800201{
202 return &(*m_begin);
203}
204
205inline const uint8_t*
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800206EncodingImpl<encoding::Buffer>::buf () const
Wentao Shang77949212014-02-01 23:42:24 -0800207{
208 return &(*m_begin);
209}
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800210
211inline Block
212EncodingImpl<encoding::Buffer>::block () const
213{
214 return Block(m_buffer,
215 m_begin, m_end);
216}
217
Wentao Shang77949212014-02-01 23:42:24 -0800218inline void
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800219EncodingImpl<encoding::Buffer>::resize (size_t sz, bool addInFront)
Wentao Shang77949212014-02-01 23:42:24 -0800220{
221 if (addInFront)
222 {
223 size_t diff_end = m_buffer->end () - m_end;
224 size_t diff_begin = m_buffer->end () - m_begin;
225
226 Buffer* buf = new Buffer (sz);
227 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
228
229 m_buffer.reset (buf);
230
231 m_end = m_buffer->end () - diff_end;
232 m_begin = m_buffer->end () - diff_begin;
233 }
234 else
235 {
236 size_t diff_end = m_end - m_buffer->begin ();
237 size_t diff_begin = m_begin - m_buffer->begin ();
238
239 Buffer* buf = new Buffer (sz);
240 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
241
242 m_buffer.reset (buf);
243
244 m_end = m_buffer->begin () + diff_end;
245 m_begin = m_buffer->begin () + diff_begin;
246 }
247}
248
249inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800250EncodingImpl<encoding::Buffer>::begin ()
Wentao Shang77949212014-02-01 23:42:24 -0800251{
252 return m_begin;
253}
254
255inline Buffer::iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800256EncodingImpl<encoding::Buffer>::end ()
Wentao Shang77949212014-02-01 23:42:24 -0800257{
258 return m_end;
259}
260
261inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800262EncodingImpl<encoding::Buffer>::begin () const
Wentao Shang77949212014-02-01 23:42:24 -0800263{
264 return m_begin;
265}
266
267inline Buffer::const_iterator
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800268EncodingImpl<encoding::Buffer>::end () const
Wentao Shang77949212014-02-01 23:42:24 -0800269{
270 return m_end;
271}
272
273
274//////////////////////////////////////////////////////////
275// Prepend to the back of the buffer. Resize if needed. //
276//////////////////////////////////////////////////////////
277
278inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800279EncodingImpl<encoding::Buffer>::prependByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800280{
281 if (m_begin == m_buffer->begin ())
282 resize (m_buffer->size () * 2, true);
283
284 m_begin--;
285 *m_begin = val;
286 return 1;
287}
288
289inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800290EncodingImpl<encoding::Estimator>::prependByte (uint8_t val)
291{
292 m_size += 1;
293 return 1;
294}
295
296inline size_t
297EncodingImpl<encoding::Buffer>::prependByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800298{
299 if ((m_buffer->begin () + len) > m_begin)
300 resize (m_buffer->size () * 2 + len, true);
301
302 m_begin -= len;
303 std::copy (arr, arr + len, m_begin);
304 return len;
305}
306
307inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800308EncodingImpl<encoding::Estimator>::prependByteArray (const uint8_t *arr, size_t len)
309{
310 m_size += len;
311 return len;
312}
313
314inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800315EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800316{
317 if (varNumber < 253) {
318 return prependByte (static_cast<uint8_t> (varNumber));
319 }
320 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
321 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
322 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
323 }
324 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
325 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
326 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
327 }
328 else {
329 uint64_t value = htobe64 (varNumber);
330 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
331 }
332}
333
334inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800335EncodingImpl<encoding::Estimator>::prependNonNegativeInteger (uint64_t varNumber)
336{
337 if (varNumber < 253) {
338 m_size += 1;
339 return 1;
340 }
341 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
342 m_size += 2;
343 return 2;
344 }
345 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
346 m_size += 4;
347 return 4;
348 }
349 else {
350 m_size += 8;
351 return 8;
352 }
353}
354
355inline size_t
356EncodingImpl<encoding::Buffer>::prependVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800357{
358 if (varNumber < 253) {
359 prependByte (static_cast<uint8_t> (varNumber));
360 return 1;
361 }
362 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
363 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
364 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
365 prependByte (253);
366 return 3;
367 }
368 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
369 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
370 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
371 prependByte (254);
372 return 5;
373 }
374 else {
375 uint64_t value = htobe64 (varNumber);
376 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
377 prependByte (255);
378 return 9;
379 }
380}
381
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800382inline size_t
383EncodingImpl<encoding::Estimator>::prependVarNumber (uint64_t varNumber)
384{
385 if (varNumber < 253) {
386 m_size += 1;
387 return 1;
388 }
389 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
390 m_size += 3;
391 return 3;
392 }
393 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
394 m_size += 5;
395 return 5;
396 }
397 else {
398 m_size += 9;
399 return 9;
400 }
401}
402
Wentao Shang77949212014-02-01 23:42:24 -0800403/////////////////////////////////////////////////////////
404// Append to the back of the buffer. Resize if needed. //
405/////////////////////////////////////////////////////////
406
407inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800408EncodingImpl<encoding::Buffer>::appendByte (uint8_t val)
Wentao Shang77949212014-02-01 23:42:24 -0800409{
410 if (m_end == m_buffer->end ())
411 resize (m_buffer->size () * 2, false);
412
413 *m_end = val;
414 m_end++;
415 return 1;
416}
417
418inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800419EncodingImpl<encoding::Estimator>::appendByte (uint8_t val)
420{
421 return 1;
422}
423
424inline size_t
425EncodingImpl<encoding::Buffer>::appendByteArray (const uint8_t *arr, size_t len)
Wentao Shang77949212014-02-01 23:42:24 -0800426{
427 if ((m_end + len) > m_buffer->end ())
428 resize (m_buffer->size () * 2 + len, false);
429
430 std::copy (arr, arr + len, m_end);
431 m_end += len;
432 return len;
433}
434
435inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800436EncodingImpl<encoding::Estimator>::appendByteArray (const uint8_t *arr, size_t len)
437{
438 return prependByteArray(arr, len);
439}
440
441inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800442EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800443{
444 if (varNumber < 253) {
445 return appendByte (static_cast<uint8_t> (varNumber));
446 }
447 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
448 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
449 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
450 }
451 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
452 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
453 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
454 }
455 else {
456 uint64_t value = htobe64 (varNumber);
457 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
458 }
459}
460
461inline size_t
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800462EncodingImpl<encoding::Estimator>::appendNonNegativeInteger (uint64_t varNumber)
463{
464 return prependNonNegativeInteger(varNumber);
465}
466
467inline size_t
468EncodingImpl<encoding::Buffer>::appendVarNumber (uint64_t varNumber)
Wentao Shang77949212014-02-01 23:42:24 -0800469{
470 if (varNumber < 253) {
471 appendByte (static_cast<uint8_t> (varNumber));
472 return 1;
473 }
474 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
475 appendByte (253);
476 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
477 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
478 return 3;
479 }
480 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
481 appendByte (254);
482 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
483 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
484 return 5;
485 }
486 else {
487 appendByte (255);
488 uint64_t value = htobe64 (varNumber);
489 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
490 return 9;
491 }
492}
493
Alexander Afanasyev217325b2014-02-06 15:03:28 -0800494inline size_t
495EncodingImpl<encoding::Estimator>::appendVarNumber (uint64_t varNumber)
496{
497 return prependVarNumber(varNumber);
498}
499
Wentao Shang77949212014-02-01 23:42:24 -0800500} // ndn
501
502#endif // NDN_ENCODING_BUFFER_HPP