blob: b2e003e37a6db0d5ea6d19cd12ef55e993c26154 [file] [log] [blame]
Eric Newberry261dbc22015-07-22 23:18:18 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Eric Newberry8422f572017-02-04 21:53:58 -07003 * Copyright (c) 2013-2017 Regents of the University of California.
Eric Newberry261dbc22015-07-22 23:18:18 -07004 *
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#ifndef NDN_CXX_LP_PACKET_HPP
23#define NDN_CXX_LP_PACKET_HPP
24
25#include "fields.hpp"
26
27namespace ndn {
28namespace lp {
29
30class Packet
31{
32public:
33 class Error : public ndn::tlv::Error
34 {
35 public:
36 explicit
37 Error(const std::string& what)
38 : ndn::tlv::Error(what)
39 {
40 }
41 };
42
43 Packet();
44
45 explicit
46 Packet(const Block& wire);
47
48 /**
Eric Newberry261dbc22015-07-22 23:18:18 -070049 * \brief encode packet into wire format
50 */
Eric Newberry82838be2015-11-07 13:00:35 -070051 Block
Eric Newberry261dbc22015-07-22 23:18:18 -070052 wireEncode() const;
53
54 /**
55 * \brief decode packet from wire format
Eric Newberry43bf6bb2015-10-09 16:12:09 -070056 * \throws Error unknown TLV-TYPE
Eric Newberry261dbc22015-07-22 23:18:18 -070057 */
58 void
59 wireDecode(const Block& wire);
60
61public: // field access
62 /**
63 * \return true if FIELD occurs one or more times
Davide Pesavento18cf81b2015-09-12 23:36:43 +020064 * \details This is equivalent to count() > 0
Eric Newberry261dbc22015-07-22 23:18:18 -070065 */
66 template<typename FIELD>
67 bool
68 has() const
69 {
70 return count<FIELD>() > 0;
71 }
72
73 /**
74 * \return number of occurrences of FIELD
75 */
76 template<typename FIELD>
77 size_t
78 count() const
79 {
Eric Newberry261dbc22015-07-22 23:18:18 -070080 return std::count_if(m_wire.elements_begin(), m_wire.elements_end(),
81 [] (const Block& block) {
82 return block.type() == FIELD::TlvType::value; });
83 }
84
85 /**
86 * \return value of index-th occurrence of FIELD
87 * \throw std::out_of_range if index>=count()
88 */
89 template<typename FIELD>
90 typename FIELD::ValueType
91 get(size_t index = 0) const
92 {
Eric Newberry261dbc22015-07-22 23:18:18 -070093 size_t count = 0;
94 for (const Block& element : m_wire.elements()) {
95 if (element.type() != FIELD::TlvType::value) {
96 continue;
97 }
98 if (count++ == index) {
99 return FIELD::decode(element);
100 }
101 }
102
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700103 BOOST_THROW_EXCEPTION(std::out_of_range("Index out of range"));
Eric Newberry261dbc22015-07-22 23:18:18 -0700104 }
105
106 /**
107 * \return values of all occurrences of FIELD
108 */
109 template<typename FIELD>
110 std::vector<typename FIELD::ValueType>
111 list() const
112 {
113 std::vector<typename FIELD::ValueType> output;
114
Eric Newberry261dbc22015-07-22 23:18:18 -0700115 for (const Block& element : m_wire.elements()) {
116 if (element.type() != FIELD::TlvType::value) {
117 continue;
118 }
119 output.push_back(FIELD::decode(element));
120 }
121
122 return output;
123 }
124
125 /**
126 * \brief remove all occurrences of FIELD, and add a FIELD with value
Davide Pesavento18cf81b2015-09-12 23:36:43 +0200127 * \details This equivalent to clear() followed by add(value)
Eric Newberry261dbc22015-07-22 23:18:18 -0700128 */
129 template<typename FIELD>
130 Packet&
131 set(const typename FIELD::ValueType& value)
132 {
133 clear<FIELD>();
134 return add<FIELD>(value);
135 }
136
137 /**
138 * \brief add a FIELD with value
139 * \throw std::length_error if field already exists and is not repeatable
140 */
141 template<typename FIELD>
142 Packet&
143 add(const typename FIELD::ValueType& value)
144 {
145 if (!FIELD::IsRepeatable::value && has<FIELD>()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700146 BOOST_THROW_EXCEPTION(std::length_error("Field cannot be repeated"));
Eric Newberry261dbc22015-07-22 23:18:18 -0700147 }
148
149 EncodingEstimator estimator;
150 size_t estimatedSize = FIELD::encode(estimator, value);
151 EncodingBuffer buffer(estimatedSize, 0);
152 FIELD::encode(buffer, value);
153 Block block = buffer.block();
154
Eric Newberry8422f572017-02-04 21:53:58 -0700155 auto pos = std::upper_bound(m_wire.elements_begin(), m_wire.elements_end(),
156 FIELD::TlvType::value, comparePos);
Eric Newberry261dbc22015-07-22 23:18:18 -0700157 m_wire.insert(pos, block);
158
159 return *this;
160 }
161
162 /**
163 * \brief remove the index-th occurrence of FIELD
164 * \throw std::out_of_range if index>=count()
165 */
166 template<typename FIELD>
167 Packet&
168 remove(size_t index = 0)
169 {
Eric Newberry261dbc22015-07-22 23:18:18 -0700170 size_t count = 0;
Eric Newberry2a890772017-06-26 12:06:15 -0700171 for (auto it = m_wire.elements_begin(); it != m_wire.elements_end(); ++it) {
Eric Newberry261dbc22015-07-22 23:18:18 -0700172 if (it->type() == FIELD::TlvType::value) {
173 if (count == index) {
174 m_wire.erase(it);
175 return *this;
176 }
177 count++;
178 }
179 }
180
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700181 BOOST_THROW_EXCEPTION(std::out_of_range("Index out of range"));
Eric Newberry261dbc22015-07-22 23:18:18 -0700182 }
183
184 /**
185 * \brief remove all occurrences of FIELD
186 */
187 template<typename FIELD>
188 Packet&
189 clear()
190 {
Eric Newberry261dbc22015-07-22 23:18:18 -0700191 m_wire.remove(FIELD::TlvType::value);
192 return *this;
193 }
194
195private:
196 static bool
Eric Newberry8422f572017-02-04 21:53:58 -0700197 comparePos(uint64_t first, const Block& second);
Eric Newberry261dbc22015-07-22 23:18:18 -0700198
199private:
200 mutable Block m_wire;
201};
202
203} // namespace lp
204} // namespace ndn
205
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700206#endif // NDN_CXX_LP_PACKET_HPP