From 356ea2a68a1471db690ffc3995699e4ec1b073b7 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 29 May 2014 23:15:44 -0300 Subject: [PATCH] Added small option optimization to PDUOption. --- include/pdu_option.h | 121 +++++++++++++++++++++++++++++++++++---- src/dot11/dot11_mgmt.cpp | 2 +- 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/include/pdu_option.h b/include/pdu_option.h index 3fdd26b..419c3a3 100644 --- a/include/pdu_option.h +++ b/include/pdu_option.h @@ -298,9 +298,10 @@ namespace Internals { */ template class PDUOption { +private: + static const int small_buffer_size = 8; public: - typedef std::vector container_type; - typedef typename container_type::value_type data_type; + typedef uint8_t data_type; typedef OptionType option_type; /** @@ -310,8 +311,79 @@ public: * \param data The option's data(if any). */ PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0) - : option_(opt), size_(length), value_(data, data + (data ? length : 0)) { - + : option_(opt), size_(length) { + set_payload_contents(data, data + (data ? length : 0)); + } + + /** + * \brief Copy constructor. + * \param rhs The PDUOption to be copied. + */ + PDUOption(const PDUOption& rhs) { + real_size_ = 0; + *this = rhs; + } + + #if TINS_IS_CXX11 + /** + * \brief Move constructor. + * \param rhs The PDUOption to be moved. + */ + PDUOption(PDUOption&& rhs) { + real_size_ = 0; + *this = std::move(rhs); + } + + /** + * \brief Move assignment operator. + * \param rhs The PDUOption to be moved. + */ + PDUOption& operator=(PDUOption&& rhs) { + option_ = rhs.option_; + size_ = rhs.size_; + if(real_size_ > small_buffer_size) { + delete[] payload_.big_buffer_ptr; + } + real_size_ = rhs.real_size_; + if(real_size_ > small_buffer_size) { + payload_.big_buffer_ptr = nullptr; + std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr); + rhs.real_size_ = 0; + } + else { + std::copy( + rhs.data_ptr(), + rhs.data_ptr() + rhs.data_size(), + payload_.small_buffer + ); + } + return *this; + } + + #endif // TINS_IS_CXX11 + + /** + * \brief Copy assignment operator. + * \param rhs The PDUOption to be copied. + */ + PDUOption& operator=(const PDUOption& rhs) { + option_ = rhs.option_; + size_ = rhs.size_; + if(real_size_ > small_buffer_size) { + delete[] payload_.big_buffer_ptr; + } + real_size_ = rhs.real_size_; + set_payload_contents(rhs.data_ptr(), rhs.data_ptr() + rhs.data_size()); + return *this; + } + + /** + * \brief Destructor. + */ + ~PDUOption() { + if(real_size_ > small_buffer_size) { + delete[] payload_.big_buffer_ptr; + } } /** @@ -324,8 +396,8 @@ public: */ template PDUOption(option_type opt, ForwardIterator start, ForwardIterator end) - : option_(opt), size_(std::distance(start, end)), value_(start, end) { - + : option_(opt), size_(std::distance(start, end)) { + set_payload_contents(start, end); } /** @@ -345,8 +417,8 @@ public: */ template PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end) - : option_(opt), size_(length), value_(start, end) { - + : option_(opt), size_(length) { + set_payload_contents(start, end); } /** @@ -375,7 +447,9 @@ public: * \return const data_type& containing this option's value. */ const data_type *data_ptr() const { - return &*value_.begin(); + return real_size_ <= small_buffer_size ? + payload_.small_buffer : + payload_.big_buffer_ptr; } /** @@ -384,7 +458,7 @@ public: * This is the actual size of the data. */ size_t data_size() const { - return value_.size(); + return real_size_; } /** @@ -415,9 +489,32 @@ public: return Internals::converter::convert(*this); } private: + template + void set_payload_contents(ForwardIterator start, ForwardIterator end) { + real_size_ = std::distance(start, end); + if(real_size_ <= small_buffer_size) { + std::copy( + start, + end, + payload_.small_buffer + ); + } + else { + payload_.big_buffer_ptr = new data_type[real_size_]; + std::copy( + start, + end, + payload_.big_buffer_ptr + ); + } + } + option_type option_; - uint16_t size_; - container_type value_; + uint16_t size_, real_size_; + union { + data_type small_buffer[small_buffer_size]; + data_type* big_buffer_ptr; + } payload_; }; } // namespace Tins #endif // TINS_PDU_OPTION_H diff --git a/src/dot11/dot11_mgmt.cpp b/src/dot11/dot11_mgmt.cpp index 8688d40..8651836 100644 --- a/src/dot11/dot11_mgmt.cpp +++ b/src/dot11/dot11_mgmt.cpp @@ -120,7 +120,7 @@ void Dot11ManagementFrame::rsn_information(const RSNInformation& info) { uint8_t *Dot11ManagementFrame::serialize_rates(const rates_type &rates) { uint8_t *buffer = new uint8_t[rates.size()], *ptr = buffer; for(rates_type::const_iterator it = rates.begin(); it != rates.end(); ++it) { - uint8_t result = static_cast(*it) * 2; + uint8_t result = static_cast(*it * 2); if(result == 2 || result == 4 || result == 11 || result == 22) result |= 0x80; *(ptr++) = result;