encoder.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2023 Regents of the University of California.
4  *
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 
23 
24 #include <boost/endian/conversion.hpp>
25 
26 namespace ndn::encoding {
27 
28 namespace endian = boost::endian;
29 
30 Encoder::Encoder(size_t totalReserve, size_t reserveFromBack)
31  : m_buffer(make_shared<Buffer>(totalReserve))
32 {
33  m_begin = m_end = m_buffer->end() - (reserveFromBack < totalReserve ? reserveFromBack : 0);
34 }
35 
36 Encoder::Encoder(const Block& block)
37  : m_buffer(std::const_pointer_cast<Buffer>(block.getBuffer()))
38  , m_begin(m_buffer->begin() + (block.begin() - m_buffer->begin()))
39  , m_end(m_buffer->begin() + (block.end() - m_buffer->begin()))
40 {
41 }
42 
43 void
45 {
46  if (m_end + size > m_buffer->end())
47  reserve(m_buffer->size() * 2 + size, false);
48 }
49 
50 void
52 {
53  if (m_buffer->begin() + size > m_begin)
54  reserve(m_buffer->size() * 2 + size, true);
55 }
56 
57 Block
58 Encoder::block(bool verifyLength) const
59 {
60  return Block(m_buffer, m_begin, m_end, verifyLength);
61 }
62 
63 void
64 Encoder::reserve(size_t size, bool addInFront)
65 {
66  if (size < m_buffer->size()) {
67  size = m_buffer->size();
68  }
69 
70  if (addInFront) {
71  size_t diffEnd = m_buffer->end() - m_end;
72  size_t diffBegin = m_buffer->end() - m_begin;
73 
74  Buffer* buf = new Buffer(size);
75  std::copy_backward(m_buffer->begin(), m_buffer->end(), buf->end());
76 
77  m_buffer.reset(buf);
78 
79  m_end = m_buffer->end() - diffEnd;
80  m_begin = m_buffer->end() - diffBegin;
81  }
82  else {
83  size_t diffEnd = m_end - m_buffer->begin();
84  size_t diffBegin = m_begin - m_buffer->begin();
85 
86  Buffer* buf = new Buffer(size);
87  std::copy(m_buffer->begin(), m_buffer->end(), buf->begin());
88 
89  m_buffer.reset(buf);
90 
91  m_end = m_buffer->begin() + diffEnd;
92  m_begin = m_buffer->begin() + diffBegin;
93  }
94 }
95 
96 size_t
97 Encoder::prependBytes(span<const uint8_t> bytes)
98 {
99  return prependRange(bytes.begin(), bytes.end());
100 }
101 
102 size_t
103 Encoder::appendBytes(span<const uint8_t> bytes)
104 {
105  return appendRange(bytes.begin(), bytes.end());
106 }
107 
108 size_t
109 Encoder::prependVarNumber(uint64_t varNumber)
110 {
111  if (varNumber < 253) {
112  prependBytes({static_cast<uint8_t>(varNumber)});
113  return 1;
114  }
115  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
116  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
117  prependBytes({reinterpret_cast<const uint8_t*>(&value), 2});
118  prependBytes({253});
119  return 3;
120  }
121  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
122  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
123  prependBytes({reinterpret_cast<const uint8_t*>(&value), 4});
124  prependBytes({254});
125  return 5;
126  }
127  else {
128  uint64_t value = endian::native_to_big(varNumber);
129  prependBytes({reinterpret_cast<const uint8_t*>(&value), 8});
130  prependBytes({255});
131  return 9;
132  }
133 }
134 
135 size_t
136 Encoder::appendVarNumber(uint64_t varNumber)
137 {
138  if (varNumber < 253) {
139  appendBytes({static_cast<uint8_t>(varNumber)});
140  return 1;
141  }
142  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
143  appendBytes({253});
144  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
145  appendBytes({reinterpret_cast<const uint8_t*>(&value), 2});
146  return 3;
147  }
148  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
149  appendBytes({254});
150  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
151  appendBytes({reinterpret_cast<const uint8_t*>(&value), 4});
152  return 5;
153  }
154  else {
155  appendBytes({255});
156  uint64_t value = endian::native_to_big(varNumber);
157  appendBytes({reinterpret_cast<const uint8_t*>(&value), 8});
158  return 9;
159  }
160 }
161 
162 size_t
164 {
165  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
166  return prependBytes({static_cast<uint8_t>(varNumber)});
167  }
168  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
169  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
170  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 2});
171  }
172  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
173  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
174  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 4});
175  }
176  else {
177  uint64_t value = endian::native_to_big(varNumber);
178  return prependBytes({reinterpret_cast<const uint8_t*>(&value), 8});
179  }
180 }
181 
182 size_t
184 {
185  if (varNumber <= std::numeric_limits<uint8_t>::max()) {
186  return appendBytes({static_cast<uint8_t>(varNumber)});
187  }
188  else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
189  uint16_t value = endian::native_to_big(static_cast<uint16_t>(varNumber));
190  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 2});
191  }
192  else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
193  uint32_t value = endian::native_to_big(static_cast<uint32_t>(varNumber));
194  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 4});
195  }
196  else {
197  uint64_t value = endian::native_to_big(varNumber);
198  return appendBytes({reinterpret_cast<const uint8_t*>(&value), 8});
199  }
200 }
201 
202 } // namespace ndn::encoding
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
General-purpose automatically managed/resized buffer.
Definition: buffer.hpp:43
void reserve(size_t size, bool addInFront)
Reserve size bytes for the underlying buffer.
Definition: encoder.cpp:64
size_t size() const noexcept
Returns the size of the encoded buffer.
Definition: encoder.hpp:226
Encoder(size_t totalReserve=MAX_NDN_PACKET_SIZE, size_t reserveFromBack=400)
Create instance of the encoder with the specified reserved sizes.
Definition: encoder.cpp:30
size_t appendBytes(span< const uint8_t > bytes)
Append a sequence of bytes.
Definition: encoder.cpp:103
void reserveFront(size_t size)
Reserve at least isze bytes at the beginning of the underlying buffer.
Definition: encoder.cpp:51
Block block(bool verifyLength=true) const
Create Block from the underlying buffer.
Definition: encoder.cpp:58
size_t prependBytes(span< const uint8_t > bytes)
Prepend a sequence of bytes.
Definition: encoder.cpp:97
size_t prependRange(Iterator first, Iterator last)
Prepend range of bytes from the range [first, last)
Definition: encoder.hpp:252
size_t prependVarNumber(uint64_t number)
Prepend number encoded as a VAR-NUMBER in NDN-TLV format.
Definition: encoder.cpp:109
size_t prependNonNegativeInteger(uint64_t integer)
Prepend integer encoded as a NonNegativeInteger in NDN-TLV format.
Definition: encoder.cpp:163
size_t appendNonNegativeInteger(uint64_t integer)
Append integer encoded as a NonNegativeInteger in NDN-TLV format.
Definition: encoder.cpp:183
size_t appendRange(Iterator first, Iterator last)
Append range of bytes from the range [first, last)
Definition: encoder.hpp:267
size_t appendVarNumber(uint64_t number)
Append number encoded as a VAR-NUMBER in NDN-TLV format.
Definition: encoder.cpp:136
void reserveBack(size_t size)
Reserve at least size bytes at the back of the underlying buffer.
Definition: encoder.cpp:44