All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
encoding-buffer.hpp
Go to the documentation of this file.
1 /* -*- 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 <[email protected]>
8  */
9 
10 #ifndef NDN_ENCODING_BUFFER_HPP
11 #define NDN_ENCODING_BUFFER_HPP
12 
13 #include "../common.hpp"
14 
15 #include "buffer.hpp"
16 #include "tlv.hpp"
17 #include "block.hpp"
18 
19 #include <boost/lexical_cast.hpp>
20 
21 namespace ndn {
22 
23 namespace encoding {
24 static const bool Buffer = true;
25 static const bool Estimator = false;
26 } // encoding
27 
28 template<bool isRealEncoderNotEstimator>
29 class EncodingImpl;
30 
33 
37 template<>
38 class EncodingImpl<encoding::Buffer>
39 {
40 public:
47  EncodingImpl(size_t totalReserve = 8800,
48  size_t reserveFromBack = 400)
49  : m_buffer(new Buffer(totalReserve))
50  {
51  m_begin = m_end = m_buffer->end() - (reserveFromBack < totalReserve ? reserveFromBack : 0);
52  }
53 
64  explicit
65  EncodingImpl(const Block& block)
66  : m_buffer(const_pointer_cast<Buffer>(block.m_buffer))
67  , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
68  , m_end(m_buffer->begin() + (block.end() - m_buffer->begin()))
69  {
70  }
71 
72  inline size_t
73  size() const;
74 
75  inline size_t
76  capacity() const;
77 
78  inline uint8_t*
79  buf();
80 
81  inline const uint8_t*
82  buf() const;
83 
91  inline Block
92  block(bool verifyLength = true) const;
93 
94  inline void
95  resize(size_t size, bool addInFront);
96 
97  inline Buffer::iterator
98  begin();
99 
100  inline Buffer::iterator
101  end();
102 
103  inline Buffer::const_iterator
104  begin() const;
105 
106  inline Buffer::const_iterator
107  end() const;
108 
109  inline size_t
110  prependByte(uint8_t value);
111 
112  inline size_t
113  prependByteArray(const uint8_t* array, size_t length);
114 
115  inline size_t
116  prependNonNegativeInteger(uint64_t varNumber);
117 
118  inline size_t
119  prependVarNumber(uint64_t varNumber);
120 
121  inline size_t
122  appendByte(uint8_t value);
123 
124  inline size_t
125  appendByteArray(const uint8_t* array, size_t length);
126 
127  inline size_t
128  appendNonNegativeInteger(uint64_t varNumber);
129 
130  inline size_t
131  appendVarNumber(uint64_t varNumber);
132 
133  // inline void
134  // removeByteFromFront();
135 
136  // inline void
137  // removeByteFromEnd();
138 
139  // inline void
140  // removeVarNumberFromFront(uint64_t varNumber);
141 
142  // inline void
143  // removeVarNumberFromBack(uint64_t varNumber);
144 
145 private:
146  BufferPtr m_buffer;
147 
148  // invariant: m_begin always points to the position of last-written byte (if prepending data)
149  Buffer::iterator m_begin;
150  // invariant: m_end always points to the position of next unwritten byte (if appending data)
151  Buffer::iterator m_end;
152 
153  friend class Block;
154 };
155 
156 
160 template<>
161 class EncodingImpl<encoding::Estimator>
162 {
163 public:
164  EncodingImpl(size_t totalReserve = 8800,
165  size_t reserveFromBack = 400)
166  {
167  }
168 
169  inline size_t
170  prependByte(uint8_t value);
171 
172  inline size_t
173  prependByteArray(const uint8_t* array, size_t length);
174 
175  inline size_t
176  prependNonNegativeInteger(uint64_t varNumber);
177 
178  inline size_t
179  prependVarNumber(uint64_t varNumber);
180 
181  inline size_t
182  appendByte(uint8_t value);
183 
184  inline size_t
185  appendByteArray(const uint8_t* array, size_t length);
186 
187  inline size_t
188  appendNonNegativeInteger(uint64_t varNumber);
189 
190  inline size_t
191  appendVarNumber(uint64_t varNumber);
192 };
193 
194 
198 
199 inline size_t
201 {
202  return m_end - m_begin;
203 }
204 
205 inline size_t
207 {
208  return m_buffer->size();
209 }
210 
211 inline uint8_t*
213 {
214  return &(*m_begin);
215 }
216 
217 inline const uint8_t*
219 {
220  return &(*m_begin);
221 }
222 
223 inline Block
224 EncodingImpl<encoding::Buffer>::block(bool verifyLength/* = true*/) const
225 {
226  return Block(m_buffer,
227  m_begin, m_end,
228  verifyLength);
229 }
230 
231 inline void
232 EncodingImpl<encoding::Buffer>::resize(size_t size, bool addInFront)
233 {
234  if (addInFront)
235  {
236  size_t diff_end = m_buffer->end() - m_end;
237  size_t diff_begin = m_buffer->end() - m_begin;
238 
239  Buffer* buf = new Buffer(size);
240  std::copy_backward(m_buffer->begin(), m_buffer->end(), buf->end());
241 
242  m_buffer.reset(buf);
243 
244  m_end = m_buffer->end() - diff_end;
245  m_begin = m_buffer->end() - diff_begin;
246  }
247  else
248  {
249  size_t diff_end = m_end - m_buffer->begin();
250  size_t diff_begin = m_begin - m_buffer->begin();
251 
252  Buffer* buf = new Buffer(size);
253  std::copy(m_buffer->begin(), m_buffer->end(), buf->begin());
254 
255  m_buffer.reset(buf);
256 
257  m_end = m_buffer->begin() + diff_end;
258  m_begin = m_buffer->begin() + diff_begin;
259  }
260 }
261 
262 inline Buffer::iterator
264 {
265  return m_begin;
266 }
267 
268 inline Buffer::iterator
270 {
271  return m_end;
272 }
273 
274 inline Buffer::const_iterator
276 {
277  return m_begin;
278 }
279 
280 inline Buffer::const_iterator
282 {
283  return m_end;
284 }
285 
286 
288 // Prepend to the back of the buffer. Resize if needed. //
290 
291 inline size_t
293 {
294  if (m_begin == m_buffer->begin())
295  resize(m_buffer->size() * 2, true);
296 
297  m_begin--;
298  *m_begin = value;
299  return 1;
300 }
301 
302 inline size_t
304 {
305  return 1;
306 }
307 
308 inline size_t
309 EncodingImpl<encoding::Buffer>::prependByteArray(const uint8_t* array, size_t length)
310 {
311  if ((m_buffer->begin() + length) > m_begin)
312  resize(m_buffer->size() * 2 + length, true);
313 
314  m_begin -= length;
315  std::copy(array, array + length, m_begin);
316  return length;
317 }
318 
319 inline size_t
320 EncodingImpl<encoding::Estimator>::prependByteArray(const uint8_t* array, size_t length)
321 {
322  return length;
323 }
324 
325 inline size_t
327 {
328  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
329  return prependByte(static_cast<uint8_t>(varNumber));
330  }
331  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
332  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
333  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
334  }
335  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
336  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
337  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
338  }
339  else {
340  uint64_t value = htobe64(varNumber);
341  return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
342  }
343 }
344 
345 inline size_t
347 {
348  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
349  return 1;
350  }
351  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
352  return 2;
353  }
354  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
355  return 4;
356  }
357  else {
358  return 8;
359  }
360 }
361 
362 inline size_t
364 {
365  if (varNumber < 253) {
366  prependByte(static_cast<uint8_t>(varNumber));
367  return 1;
368  }
369  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
370  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
371  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
372  prependByte(253);
373  return 3;
374  }
375  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
376  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
377  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
378  prependByte(254);
379  return 5;
380  }
381  else {
382  uint64_t value = htobe64(varNumber);
383  prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
384  prependByte(255);
385  return 9;
386  }
387 }
388 
389 inline size_t
391 {
392  if (varNumber < 253) {
393  return 1;
394  }
395  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
396  return 3;
397  }
398  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
399  return 5;
400  }
401  else {
402  return 9;
403  }
404 }
405 
407 // Append to the back of the buffer. Resize if needed. //
409 
410 inline size_t
412 {
413  if (m_end == m_buffer->end())
414  resize(m_buffer->size() * 2, false);
415 
416  *m_end = value;
417  m_end++;
418  return 1;
419 }
420 
421 inline size_t
423 {
424  return 1;
425 }
426 
427 inline size_t
428 EncodingImpl<encoding::Buffer>::appendByteArray(const uint8_t* array, size_t length)
429 {
430  if ((m_end + length) > m_buffer->end())
431  resize(m_buffer->size() * 2 + length, false);
432 
433  std::copy(array, array + length, m_end);
434  m_end += length;
435  return length;
436 }
437 
438 inline size_t
439 EncodingImpl<encoding::Estimator>::appendByteArray(const uint8_t* array, size_t length)
440 {
441  return prependByteArray(array, length);
442 }
443 
444 inline size_t
446 {
447  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
448  return appendByte(static_cast<uint8_t>(varNumber));
449  }
450  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
451  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
452  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
453  }
454  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
455  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
456  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
457  }
458  else {
459  uint64_t value = htobe64(varNumber);
460  return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
461  }
462 }
463 
464 inline size_t
466 {
467  return prependNonNegativeInteger(varNumber);
468 }
469 
470 inline size_t
472 {
473  if (varNumber < 253) {
474  appendByte(static_cast<uint8_t>(varNumber));
475  return 1;
476  }
477  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
478  appendByte(253);
479  uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
480  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
481  return 3;
482  }
483  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
484  appendByte(254);
485  uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
486  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
487  return 5;
488  }
489  else {
490  appendByte(255);
491  uint64_t value = htobe64(varNumber);
492  appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
493  return 9;
494  }
495 }
496 
497 inline size_t
499 {
500  return prependVarNumber(varNumber);
501 }
502 
504 
505 template<bool P>
506 inline size_t
507 prependNonNegativeIntegerBlock(EncodingImpl<P>& encoder, uint32_t type, uint64_t number)
508 {
509  size_t valueLength = encoder.prependNonNegativeInteger(number);
510  size_t totalLength = valueLength;
511  totalLength += encoder.prependVarNumber(valueLength);
512  totalLength += encoder.prependVarNumber(type);
513 
514  return totalLength;
515 }
516 
517 template<bool P>
518 inline size_t
519 prependByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
520  const uint8_t* array, size_t arraySize)
521 {
522  size_t valueLength = encoder.prependByteArray(array, arraySize);
523  size_t totalLength = valueLength;
524  totalLength += encoder.prependVarNumber(valueLength);
525  totalLength += encoder.prependVarNumber(type);
526 
527  return totalLength;
528 }
529 
530 template<bool P>
531 inline size_t
532 prependBooleanBlock(EncodingImpl<P>& encoder, uint32_t type)
533 {
534  size_t totalLength = encoder.prependVarNumber(0);
535  totalLength += encoder.prependVarNumber(type);
536 
537  return totalLength;
538 }
539 
540 
541 template<bool P, class U>
542 inline size_t
543 prependNestedBlock(EncodingImpl<P>& encoder, uint32_t type, const U& nestedBlock)
544 {
545  size_t valueLength = nestedBlock.wireEncode(encoder);
546  size_t totalLength = valueLength;
547  totalLength += encoder.prependVarNumber(valueLength);
548  totalLength += encoder.prependVarNumber(type);
549 
550  return totalLength;
551 }
552 
553 template<bool P>
554 inline size_t
555 prependBlock(EncodingImpl<P>& encoder, const Block& block)
556 {
557  return encoder.prependByteArray(block.wire(), block.size());
558 }
559 
560 
561 } // ndn
562 
563 #endif // NDN_ENCODING_BUFFER_HPP
EncodingImpl(const Block &block)
Create EncodingBlock from existing block.
size_t prependNestedBlock(EncodingImpl< P > &encoder, uint32_t type, const U &nestedBlock)
static const bool Estimator
Class representing wire element of the NDN packet.
ptr_lib::shared_ptr< Buffer > BufferPtr
Definition: buffer.hpp:19
EncodingImpl< true > EncodingBuffer
Definition: block.hpp:20
Class representing wire element of the NDN packet.
Definition: block.hpp:26
static const bool Buffer
size_t size() const
Definition: block.hpp:415
size_t prependBlock(EncodingImpl< P > &encoder, const Block &block)
EncodingImpl(size_t totalReserve=8800, size_t reserveFromBack=400)
Constructor to create a EncodingImpl with specified reserved sizes.
size_t prependBooleanBlock(EncodingImpl< P > &encoder, uint32_t type)
EncodingImpl< encoding::Estimator > EncodingEstimator
EncodingImpl(size_t totalReserve=8800, size_t reserveFromBack=400)
const uint8_t * wire() const
Definition: block.hpp:437
size_t prependNonNegativeIntegerBlock(EncodingImpl< P > &encoder, uint32_t type, uint64_t number)
helper methods
Class representing a general-use automatically managed/resized buffer.
Definition: buffer.hpp:28
size_t prependByteArrayBlock(EncodingImpl< P > &encoder, uint32_t type, const uint8_t *array, size_t arraySize)
Class representing wire element of the NDN packet.