1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Added small option optimization to PDUOption.

This commit is contained in:
Matias Fontanini
2014-05-29 23:15:44 -03:00
parent 559c963d63
commit 356ea2a68a
2 changed files with 110 additions and 13 deletions

View File

@@ -298,9 +298,10 @@ namespace Internals {
*/
template<typename OptionType, class PDUType>
class PDUOption {
private:
static const int small_buffer_size = 8;
public:
typedef std::vector<uint8_t> 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<typename ForwardIterator>
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<typename ForwardIterator>
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<T>::convert(*this);
}
private:
template<typename ForwardIterator>
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

View File

@@ -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<uint8_t>(*it) * 2;
uint8_t result = static_cast<uint8_t>(*it * 2);
if(result == 2 || result == 4 || result == 11 || result == 22)
result |= 0x80;
*(ptr++) = result;