30 #ifndef TINS_PDU_OPTION_H 31 #define TINS_PDU_OPTION_H 37 #include <tins/exceptions.h> 38 #include <tins/detail/type_traits.h> 50 template <
typename OptionType,
typename PDUType>
54 namespace Converters {
55 uint8_t convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
56 type_to_type<uint8_t>);
57 int8_t convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
58 type_to_type<int8_t>);
59 uint16_t convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
60 type_to_type<uint16_t>);
61 uint32_t convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
62 type_to_type<uint32_t>);
63 uint64_t convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
64 type_to_type<uint64_t>);
65 HWAddress<6> convert(
const uint8_t* ptr, uint32_t data_size,
67 IPv4Address convert(
const uint8_t* ptr, uint32_t data_size,
69 IPv6Address convert(
const uint8_t* ptr, uint32_t data_size,
PDU::endian_type endian,
70 type_to_type<IPv6Address>);
71 std::string convert(
const uint8_t* ptr, uint32_t data_size,
73 std::vector<float> convert(
const uint8_t* ptr, uint32_t data_size,
75 std::vector<uint8_t> convert(
const uint8_t* ptr, uint32_t data_size,
77 std::vector<uint16_t> convert(
const uint8_t* ptr, uint32_t data_size,
79 type_to_type<std::vector<uint16_t> >);
80 std::vector<uint32_t> convert(
const uint8_t* ptr, uint32_t data_size,
82 type_to_type<std::vector<uint32_t> >);
83 std::vector<IPv4Address> convert(
const uint8_t* ptr, uint32_t data_size,
85 type_to_type<std::vector<IPv4Address> >);
86 std::vector<IPv6Address> convert(
const uint8_t* ptr, uint32_t data_size,
88 type_to_type<std::vector<IPv6Address> >);
89 std::vector<std::pair<uint8_t, uint8_t> > convert(
const uint8_t* ptr, uint32_t data_size,
91 type_to_type<std::vector<std::pair<uint8_t, uint8_t> > >);
92 std::pair<uint8_t, uint8_t> convert(
const uint8_t* ptr, uint32_t data_size,
94 type_to_type<std::pair<uint8_t, uint8_t> >);
95 std::pair<uint16_t, uint32_t> convert(
const uint8_t* ptr, uint32_t data_size,
97 type_to_type<std::pair<uint16_t, uint32_t> >);
98 std::pair<uint32_t, uint32_t> convert(
const uint8_t* ptr, uint32_t data_size,
100 type_to_type<std::pair<uint32_t, uint32_t> >);
104 template <
typename T,
typename X,
typename PDUType>
105 static T do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<T>) {
106 return T::from_option(opt);
109 template <
typename U,
typename X,
typename PDUType>
110 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<uint8_t> type) {
111 return Converters::convert(opt.data_ptr(), opt.data_size(),
112 PDUType::endianness, type);
115 template <
typename U,
typename X,
typename PDUType>
116 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<int8_t> type) {
117 return Converters::convert(opt.data_ptr(), opt.data_size(),
118 PDUType::endianness, type);
121 template <
typename U,
typename X,
typename PDUType>
122 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<uint16_t> type) {
123 return Converters::convert(opt.data_ptr(), opt.data_size(),
124 PDUType::endianness, type);
127 template <
typename U,
typename X,
typename PDUType>
128 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<uint32_t> type) {
129 return Converters::convert(opt.data_ptr(), opt.data_size(),
130 PDUType::endianness, type);
133 template <
typename U,
typename X,
typename PDUType>
134 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<uint64_t> type) {
135 return Converters::convert(opt.data_ptr(), opt.data_size(),
136 PDUType::endianness, type);
139 template <
typename U,
typename X,
typename PDUType>
140 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<HWAddress<6> > type) {
141 return Converters::convert(opt.data_ptr(), opt.data_size(),
142 PDUType::endianness, type);
145 template <
typename U,
typename X,
typename PDUType>
146 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<IPv4Address> type) {
147 return Converters::convert(opt.data_ptr(), opt.data_size(),
148 PDUType::endianness, type);
151 template <
typename U,
typename X,
typename PDUType>
152 static U do_convert(
const PDUOption<X, PDUType>& opt, type_to_type<IPv6Address> type) {
153 return Converters::convert(opt.data_ptr(), opt.data_size(),
154 PDUType::endianness, type);
157 template <
typename U,
typename X,
typename PDUType>
158 static U do_convert(
const PDUOption<X, PDUType>& opt,
159 type_to_type<std::string> type) {
160 return Converters::convert(opt.data_ptr(), opt.data_size(),
161 PDUType::endianness, type);
164 template <
typename U,
typename X,
typename PDUType,
typename Z>
165 static U do_convert(
const PDUOption<X, PDUType>& opt,
166 type_to_type<std::vector<Z> > type) {
167 return Converters::convert(opt.data_ptr(), opt.data_size(),
168 PDUType::endianness, type);
171 template <
typename U,
typename X,
typename PDUType,
typename Z,
typename W>
172 static U do_convert(
const PDUOption<X, PDUType>& opt,
173 type_to_type<std::pair<Z, W> > type) {
174 return Converters::convert(opt.data_ptr(), opt.data_size(),
175 PDUType::endianness, type);
178 template <
typename T,
typename X,
typename PDUType>
179 static T convert(
const PDUOption<X, PDUType>& opt) {
180 return do_convert<T>(opt, type_to_type<T>());
200 template <
typename OptionType,
typename PDUType>
203 static const int small_buffer_size = 8;
205 typedef uint8_t data_type;
206 typedef OptionType option_type;
216 const data_type* data = 0)
217 : option_(opt), size_(static_cast<uint16_t>(length)), real_size_(0) {
219 set_payload_contents(data, data + length);
239 *
this = std::move(rhs);
247 option_ = rhs.option_;
249 if (real_size_ > small_buffer_size) {
250 delete[] payload_.big_buffer_ptr;
252 real_size_ = rhs.real_size_;
253 if (real_size_ > small_buffer_size) {
254 payload_.big_buffer_ptr = 0;
255 std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr);
259 std::memcpy(payload_.small_buffer, rhs.data_ptr(), rhs.data_size());
264 #endif // TINS_IS_CXX11 271 option_ = rhs.option_;
273 if (real_size_ > small_buffer_size) {
274 delete[] payload_.big_buffer_ptr;
276 real_size_ = rhs.real_size_;
285 if (real_size_ > small_buffer_size) {
286 delete[] payload_.big_buffer_ptr;
298 template<
typename ForwardIterator>
299 PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
300 : option_(opt), size_(static_cast<uint16_t>(
std::distance(start, end))) {
301 set_payload_contents(start, end);
319 template<
typename ForwardIterator>
320 PDUOption(option_type opt, uint16_t length, ForwardIterator start, ForwardIterator end)
321 : option_(opt), size_(length) {
322 set_payload_contents(start, end);
351 return real_size_ <= small_buffer_size ?
352 payload_.small_buffer :
353 payload_.big_buffer_ptr;
390 return Internals::converter::convert<T>(*this);
393 template<
typename ForwardIterator>
394 void set_payload_contents(ForwardIterator start, ForwardIterator end) {
395 size_t total_size = std::distance(start, end);
396 if (total_size > 65535) {
399 real_size_ =
static_cast<uint16_t
>(total_size);
400 if (real_size_ <= small_buffer_size) {
401 if (total_size > 0) {
402 std::memcpy(payload_.small_buffer, &*start, total_size);
406 payload_.big_buffer_ptr =
new data_type[real_size_];
407 uint8_t* ptr = payload_.big_buffer_ptr;
408 while (start < end) {
417 uint16_t size_, real_size_;
419 data_type small_buffer[small_buffer_size];
420 data_type* big_buffer_ptr;
424 namespace Internals {
429 template <
typename Option,
typename Container>
430 typename Container::iterator find_option(Container& cont,
typename Option::option_type type) {
431 typename Container::iterator iter;
432 for (iter = cont.begin(); iter != cont.end(); ++iter) {
433 if (iter->option() == type) {
440 template <
typename Option,
typename Container>
441 typename Container::const_iterator find_option_const(
const Container& cont,
442 typename Option::option_type type) {
443 typename Container::const_iterator iter;
444 for (iter = cont.begin(); iter != cont.end(); ++iter) {
445 if (iter->option() == type) {
458 #endif // TINS_PDU_OPTION_H PDUOption & operator=(PDUOption &&rhs) TINS_NOEXCEPT
Move assignment operator.
Definition: pdu_option.h:246
~PDUOption()
Destructor.
Definition: pdu_option.h:284
size_t length_field() const
Retrieves the data length field.
Definition: pdu_option.h:377
PDUOption(PDUOption &&rhs) TINS_NOEXCEPT
Move constructor.
Definition: pdu_option.h:237
Definition: hw_address.h:456
Represents a PDU option field.
Definition: pdu_option.h:201
const data_type * data_ptr() const
Definition: pdu_option.h:350
PDUOption(option_type opt=option_type(), size_t length=0, const data_type *data=0)
Constructs a PDUOption.
Definition: pdu_option.h:214
PDUOption(const PDUOption &rhs)
Copy constructor.
Definition: pdu_option.h:227
The Tins namespace.
Definition: address_range.h:38
void option(option_type opt)
Definition: pdu_option.h:337
T to() const
Constructs a T from this PDUOption.
Definition: pdu_option.h:389
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
Constructs a PDUOption from iterators, which indicate the data to be stored in it.
Definition: pdu_option.h:299
option_type option() const
Definition: pdu_option.h:329
PDUOption & operator=(const PDUOption &rhs)
Copy assignment operator.
Definition: pdu_option.h:270
size_t data_size() const
Retrieves the length of this option's data.
Definition: pdu_option.h:361
endian_type
Definition: pdu.h:117
Exception thrown when a payload is too large to fit into a PDUOption.
Definition: exceptions.h:202
PDUOption(option_type opt, uint16_t length, ForwardIterator start, ForwardIterator end)
Constructs a PDUOption from iterators, which indicate the data to be stored in it.
Definition: pdu_option.h:320