blob: b3cfa6580102ef671c4da265b7eaa55efef23114 [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
26/**
27 * @brief Class representing wire element of the NDN packet
28 */
29class EncodingBuffer
30{
31public:
32 /// @brief Error that can be thrown from the block
33 struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
34
35 enum
36 {
37 DefaultBufferSize = 8800,
38 BufferReservedSize = 400
39 };
40
41 /**
42 * @brief Default constructor to create a fix-sized EncodingBuffer
43 */
44 EncodingBuffer ()
45 : m_buffer (new Buffer ((size_t) DefaultBufferSize))
46 {
47 m_begin = m_end = m_buffer->end () - BufferReservedSize;
48 }
49
50 /**
51 * @brief Constructor to create a EncodingBuffer with user-specified size
52 */
53 EncodingBuffer (size_t size)
54 : m_buffer (new Buffer (size))
55 {
56 if (size <= BufferReservedSize)
57 m_begin = m_end = m_buffer->end ();
58 else
59 m_begin = m_end = m_buffer->end () - BufferReservedSize;
60 }
61
62 inline size_t
63 size () const;
64
65 inline size_t
66 capacity () const;
67
68 inline uint8_t*
69 buf ();
70
71 inline const uint8_t*
72 buf () const;
73
74 inline void
75 resize (size_t sz, bool addInFront);
76
77 inline Buffer::iterator
78 begin ();
79
80 inline Buffer::iterator
81 end ();
82
83 inline Buffer::const_iterator
84 begin () const;
85
86 inline Buffer::const_iterator
87 end () const;
88
89 inline size_t
90 prependByte (uint8_t val);
91
92 inline size_t
93 prependByteArray (const uint8_t *arr, size_t len);
94
95 inline size_t
96 prependBuffer (const Buffer& arr);
97
98 inline size_t
99 prependNonNegativeInteger (uint64_t varNumber);
100
101 inline size_t
102 prependVarNumber (uint64_t varNumber);
103
104 inline size_t
105 appendByte (uint8_t val);
106
107 inline size_t
108 appendByteArray (const uint8_t *arr, size_t len);
109
110 inline size_t
111 appendBuffer (const Buffer& arr);
112
113 inline size_t
114 appendNonNegativeInteger (uint64_t varNumber);
115
116 inline size_t
117 appendVarNumber (uint64_t varNumber);
118
119private:
120 BufferPtr m_buffer;
121
122 // invariant: m_begin always points to the position of last-written byte (if prepending data)
123 Buffer::iterator m_begin;
124 // invariant: m_end always points to the position of next unwritten byte (if appending data)
125 Buffer::iterator m_end;
126};
127
128////////////////////////////////////////////////////////////////////////////////
129////////////////////////////////////////////////////////////////////////////////
130////////////////////////////////////////////////////////////////////////////////
131
132inline size_t
133EncodingBuffer::size () const
134{
135 return m_end - m_begin;
136}
137
138inline size_t
139EncodingBuffer::capacity () const
140{
141 return m_buffer->size ();
142}
143
144inline uint8_t*
145EncodingBuffer::buf ()
146{
147 return &(*m_begin);
148}
149
150inline const uint8_t*
151EncodingBuffer::buf () const
152{
153 return &(*m_begin);
154}
155
156inline void
157EncodingBuffer::resize (size_t sz, bool addInFront)
158{
159 if (addInFront)
160 {
161 size_t diff_end = m_buffer->end () - m_end;
162 size_t diff_begin = m_buffer->end () - m_begin;
163
164 Buffer* buf = new Buffer (sz);
165 std::copy_backward (m_buffer->begin (), m_buffer->end (), buf->end ());
166
167 m_buffer.reset (buf);
168
169 m_end = m_buffer->end () - diff_end;
170 m_begin = m_buffer->end () - diff_begin;
171 }
172 else
173 {
174 size_t diff_end = m_end - m_buffer->begin ();
175 size_t diff_begin = m_begin - m_buffer->begin ();
176
177 Buffer* buf = new Buffer (sz);
178 std::copy (m_buffer->begin (), m_buffer->end (), buf->begin ());
179
180 m_buffer.reset (buf);
181
182 m_end = m_buffer->begin () + diff_end;
183 m_begin = m_buffer->begin () + diff_begin;
184 }
185}
186
187inline Buffer::iterator
188EncodingBuffer::begin ()
189{
190 return m_begin;
191}
192
193inline Buffer::iterator
194EncodingBuffer::end ()
195{
196 return m_end;
197}
198
199inline Buffer::const_iterator
200EncodingBuffer::begin () const
201{
202 return m_begin;
203}
204
205inline Buffer::const_iterator
206EncodingBuffer::end () const
207{
208 return m_end;
209}
210
211
212//////////////////////////////////////////////////////////
213// Prepend to the back of the buffer. Resize if needed. //
214//////////////////////////////////////////////////////////
215
216inline size_t
217EncodingBuffer::prependByte (uint8_t val)
218{
219 if (m_begin == m_buffer->begin ())
220 resize (m_buffer->size () * 2, true);
221
222 m_begin--;
223 *m_begin = val;
224 return 1;
225}
226
227inline size_t
228EncodingBuffer::prependByteArray (const uint8_t *arr, size_t len)
229{
230 if ((m_buffer->begin () + len) > m_begin)
231 resize (m_buffer->size () * 2 + len, true);
232
233 m_begin -= len;
234 std::copy (arr, arr + len, m_begin);
235 return len;
236}
237
238inline size_t
239EncodingBuffer::prependBuffer (const Buffer& arr)
240{
241 if ((m_buffer->begin () + arr.size ()) > m_begin)
242 resize (m_buffer->size () * 2 + arr.size (), true);
243
244 m_begin -= arr.size ();
245 std::copy (arr.begin (), arr.end (), m_begin);
246 return arr.size ();
247}
248
249inline size_t
250EncodingBuffer::prependNonNegativeInteger (uint64_t varNumber)
251{
252 if (varNumber < 253) {
253 return prependByte (static_cast<uint8_t> (varNumber));
254 }
255 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
256 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
257 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
258 }
259 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
260 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
261 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
262 }
263 else {
264 uint64_t value = htobe64 (varNumber);
265 return prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
266 }
267}
268
269inline size_t
270EncodingBuffer::prependVarNumber (uint64_t varNumber)
271{
272 if (varNumber < 253) {
273 prependByte (static_cast<uint8_t> (varNumber));
274 return 1;
275 }
276 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
277 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
278 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
279 prependByte (253);
280 return 3;
281 }
282 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
283 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
284 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
285 prependByte (254);
286 return 5;
287 }
288 else {
289 uint64_t value = htobe64 (varNumber);
290 prependByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
291 prependByte (255);
292 return 9;
293 }
294}
295
296/////////////////////////////////////////////////////////
297// Append to the back of the buffer. Resize if needed. //
298/////////////////////////////////////////////////////////
299
300inline size_t
301EncodingBuffer::appendByte (uint8_t val)
302{
303 if (m_end == m_buffer->end ())
304 resize (m_buffer->size () * 2, false);
305
306 *m_end = val;
307 m_end++;
308 return 1;
309}
310
311inline size_t
312EncodingBuffer::appendByteArray (const uint8_t *arr, size_t len)
313{
314 if ((m_end + len) > m_buffer->end ())
315 resize (m_buffer->size () * 2 + len, false);
316
317 std::copy (arr, arr + len, m_end);
318 m_end += len;
319 return len;
320}
321
322inline size_t
323EncodingBuffer::appendBuffer (const Buffer& arr)
324{
325 if ((m_end + arr.size ()) > m_buffer->end ())
326 resize (m_buffer->size () * 2 + arr.size (), false);
327
328 std::copy (arr.begin (), arr.end (), m_end);
329 m_end -= arr.size ();
330 return arr.size ();
331}
332
333inline size_t
334EncodingBuffer::appendNonNegativeInteger (uint64_t varNumber)
335{
336 if (varNumber < 253) {
337 return appendByte (static_cast<uint8_t> (varNumber));
338 }
339 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
340 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
341 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
342 }
343 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
344 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
345 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
346 }
347 else {
348 uint64_t value = htobe64 (varNumber);
349 return appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
350 }
351}
352
353inline size_t
354EncodingBuffer::appendVarNumber (uint64_t varNumber)
355{
356 if (varNumber < 253) {
357 appendByte (static_cast<uint8_t> (varNumber));
358 return 1;
359 }
360 else if (varNumber <= std::numeric_limits<uint16_t>::max ()) {
361 appendByte (253);
362 uint16_t value = htobe16 (static_cast<uint16_t> (varNumber));
363 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 2);
364 return 3;
365 }
366 else if (varNumber <= std::numeric_limits<uint32_t>::max ()) {
367 appendByte (254);
368 uint32_t value = htobe32 (static_cast<uint32_t> (varNumber));
369 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 4);
370 return 5;
371 }
372 else {
373 appendByte (255);
374 uint64_t value = htobe64 (varNumber);
375 appendByteArray (reinterpret_cast<const uint8_t*> (&value), 8);
376 return 9;
377 }
378}
379
380} // ndn
381
382#endif // NDN_ENCODING_BUFFER_HPP