blob: 12b5ea1b1ea779b1fc62f127519779d09e250c26 [file] [log] [blame]
Alexander Afanasyev74633892015-02-08 18:08:46 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi6617e492016-01-19 07:33:00 -07003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyev74633892015-02-08 18:08:46 -08004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "encoder.hpp"
23
24namespace ndn {
25namespace encoding {
26
susmit8b156552016-01-12 13:10:55 -070027Encoder::Encoder(size_t totalReserve/* = MAX_NDN_PACKET_SIZE*/, size_t reserveFromBack/* = 400*/)
Alexander Afanasyev74633892015-02-08 18:08:46 -080028 : m_buffer(new Buffer(totalReserve))
29{
30 m_begin = m_end = m_buffer->end() - (reserveFromBack < totalReserve ? reserveFromBack : 0);
31}
32
33
34Encoder::Encoder(const Block& block)
35 : m_buffer(const_pointer_cast<Buffer>(block.getBuffer()))
36 , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
37 , m_end(m_buffer->begin() + (block.end() - m_buffer->begin()))
38{
39}
40
41////////////////////////////////////////////////////////////////////////////////
42////////////////////////////////////////////////////////////////////////////////
43
44void
45Encoder::reserveBack(size_t size)
46{
47 if ((m_end + size) > m_buffer->end())
48 reserve(m_buffer->size() * 2 + size, false);
49}
50
51void
52Encoder::reserveFront(size_t size)
53{
54 if ((m_buffer->begin() + size) > m_begin)
55 reserve(m_buffer->size() * 2 + size, true);
56}
57
58
59Block
60Encoder::block(bool verifyLength/* = true*/) const
61{
62 return Block(m_buffer,
63 m_begin, m_end,
64 verifyLength);
65}
66
67void
68Encoder::reserve(size_t size, bool addInFront)
69{
70 if (size < m_buffer->size()) {
71 size = m_buffer->size();
72 }
73
74 if (addInFront) {
75 size_t diffEnd = m_buffer->end() - m_end;
76 size_t diffBegin = m_buffer->end() - m_begin;
77
78 Buffer* buf = new Buffer(size);
79 std::copy_backward(m_buffer->begin(), m_buffer->end(), buf->end());
80
81 m_buffer.reset(buf);
82
83 m_end = m_buffer->end() - diffEnd;
84 m_begin = m_buffer->end() - diffBegin;
85 }
86 else {
87 size_t diffEnd = m_end - m_buffer->begin();
88 size_t diffBegin = m_begin - m_buffer->begin();
89
90 Buffer* buf = new Buffer(size);
91 std::copy(m_buffer->begin(), m_buffer->end(), buf->begin());
92
93 m_buffer.reset(buf);
94
95 m_end = m_buffer->begin() + diffEnd;
96 m_begin = m_buffer->begin() + diffBegin;
97 }
98}
99
100////////////////////////////////////////////////////////////////////////////////
101////////////////////////////////////////////////////////////////////////////////
102
103size_t
104Encoder::prependByte(uint8_t value)
105{
106 reserveFront(1);
107
108 m_begin--;
109 *m_begin = value;
110 return 1;
111}
112
113size_t
114Encoder::appendByte(uint8_t value)
115{
116 reserveBack(1);
117
118 *m_end = value;
119 m_end++;
120 return 1;
121}
122
123
124size_t
125Encoder::prependByteArray(const uint8_t* array, size_t length)
126{
127 reserveFront(length);
128
129 m_begin -= length;
130 std::copy(array, array + length, m_begin);
131 return length;
132}
133
134size_t
135Encoder::appendByteArray(const uint8_t* array, size_t length)
136{
137 reserveBack(length);
138
139 std::copy(array, array + length, m_end);
140 m_end += length;
141 return length;
142}
143
144
145size_t
146Encoder::prependVarNumber(uint64_t varNumber)
147{
148 if (varNumber < 253) {
149 prependByte(static_cast<uint8_t>(varNumber));
150 return 1;
151 }
152 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
153 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
154 prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
155 prependByte(253);
156 return 3;
157 }
158 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
159 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
160 prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
161 prependByte(254);
162 return 5;
163 }
164 else {
165 uint64_t value = htobe64(varNumber);
166 prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
167 prependByte(255);
168 return 9;
169 }
170}
171
172size_t
173Encoder::appendVarNumber(uint64_t varNumber)
174{
175 if (varNumber < 253) {
176 appendByte(static_cast<uint8_t>(varNumber));
177 return 1;
178 }
179 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
180 appendByte(253);
181 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
182 appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
183 return 3;
184 }
185 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
186 appendByte(254);
187 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
188 appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
189 return 5;
190 }
191 else {
192 appendByte(255);
193 uint64_t value = htobe64(varNumber);
194 appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
195 return 9;
196 }
197}
198
199
200size_t
201Encoder::prependNonNegativeInteger(uint64_t varNumber)
202{
203 if (varNumber <= std::numeric_limits<uint8_t>::max()) {
204 return prependByte(static_cast<uint8_t>(varNumber));
205 }
206 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
207 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
208 return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
209 }
210 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
211 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
212 return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
213 }
214 else {
215 uint64_t value = htobe64(varNumber);
216 return prependByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
217 }
218}
219
220size_t
221Encoder::appendNonNegativeInteger(uint64_t varNumber)
222{
223 if (varNumber <= std::numeric_limits<uint8_t>::max()) {
224 return appendByte(static_cast<uint8_t>(varNumber));
225 }
226 else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
227 uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
228 return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 2);
229 }
230 else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
231 uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
232 return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 4);
233 }
234 else {
235 uint64_t value = htobe64(varNumber);
236 return appendByteArray(reinterpret_cast<const uint8_t*>(&value), 8);
237 }
238}
239
240size_t
241Encoder::prependByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
242{
243 size_t totalLength = prependByteArray(array, arraySize);
244 totalLength += prependVarNumber(arraySize);
245 totalLength += prependVarNumber(type);
246
247 return totalLength;
248}
249
250size_t
251Encoder::appendByteArrayBlock(uint32_t type, const uint8_t* array, size_t arraySize)
252{
253 size_t totalLength = appendVarNumber(type);
254 totalLength += appendVarNumber(arraySize);
255 totalLength += appendByteArray(array, arraySize);
256
257 return totalLength;
258}
259
260size_t
261Encoder::prependBlock(const Block& block)
262{
263 if (block.hasWire()) {
264 return prependByteArray(block.wire(), block.size());
265 }
266 else {
267 return prependByteArrayBlock(block.type(), block.value(), block.value_size());
268 }
269}
270
271size_t
272Encoder::appendBlock(const Block& block)
273{
274 if (block.hasWire()) {
275 return appendByteArray(block.wire(), block.size());
276 }
277 else {
278 return appendByteArrayBlock(block.type(), block.value(), block.value_size());
279 }
280}
281
282} // namespace encoding
283} // namespace ndn