From afafb32eb79343c7e1933d7f7a89dbc81b0c8171 Mon Sep 17 00:00:00 2001 From: Myles Watson Date: Tue, 16 Apr 2019 10:24:26 -0700 Subject: [PATCH] BitInserter: Add byte observer for checksums Test: bluetooth_test_gd --gtest_filter=*BitInserter* Change-Id: I9ef5bc5951244279fc142127a5c3c9a54c4eaf5c --- gd/packet/Android.bp | 2 + gd/packet/bit_inserter.cc | 147 +++++-------------------------------- gd/packet/bit_inserter.h | 32 ++------ gd/packet/bit_inserter_unittest.cc | 48 +++++++++--- gd/packet/byte_inserter.cc | 48 ++++++++++++ gd/packet/byte_inserter.h | 45 ++++++++++++ gd/packet/byte_observer.cc | 34 +++++++++ gd/packet/byte_observer.h | 39 ++++++++++ 8 files changed, 231 insertions(+), 164 deletions(-) create mode 100644 gd/packet/byte_inserter.cc create mode 100644 gd/packet/byte_inserter.h create mode 100644 gd/packet/byte_observer.cc create mode 100644 gd/packet/byte_observer.h diff --git a/gd/packet/Android.bp b/gd/packet/Android.bp index be5a3c98e..155fb4a85 100644 --- a/gd/packet/Android.bp +++ b/gd/packet/Android.bp @@ -2,6 +2,8 @@ filegroup { name: "BluetoothPacketSources", srcs: [ "bit_inserter.cc", + "byte_inserter.cc", + "byte_observer.cc", "iterator.cc", "packet_view.cc", "raw_builder.cc", diff --git a/gd/packet/bit_inserter.cc b/gd/packet/bit_inserter.cc index 516780643..0180cd834 100644 --- a/gd/packet/bit_inserter.cc +++ b/gd/packet/bit_inserter.cc @@ -14,147 +14,40 @@ * limitations under the License. */ -#include "packet/iterator.h" +#include "packet/bit_inserter.h" #include "os/log.h" namespace bluetooth { namespace packet { -template -Iterator::Iterator(std::forward_list data, size_t offset) { - data_ = data; - index_ = offset; - length_ = 0; - for (auto& view : data) { - length_ += view.size(); - } -} - -template -Iterator Iterator::operator+(int offset) { - auto itr(*this); - - return itr += offset; -} - -template -Iterator& Iterator::operator+=(int offset) { - index_ += offset; - return *this; -} - -template -Iterator Iterator::operator++(int) { - auto itr(*this); - index_++; - return itr; -} - -template -Iterator& Iterator::operator++() { - index_++; - return *this; -} - -template -Iterator Iterator::operator-(int offset) { - auto itr(*this); - - return itr -= offset; -} - -template -int Iterator::operator-(Iterator& itr) { - return index_ - itr.index_; -} - -template -Iterator& Iterator::operator-=(int offset) { - index_ -= offset; - - return *this; -} - -template -Iterator Iterator::operator--(int) { - auto itr(*this); - if (index_ != 0) index_--; +BitInserter::BitInserter(std::vector& vector) : ByteInserter(vector) {} - return itr; +BitInserter::~BitInserter() { + ASSERT(num_saved_bits_ == 0); } -template -Iterator& Iterator::operator--() { - if (index_ != 0) index_--; - - return *this; -} - -template -Iterator& Iterator::operator=(const Iterator& itr) { - data_ = itr.data_; - index_ = itr.index_; - - return *this; -} - -template -bool Iterator::operator==(const Iterator& itr) const { - return index_ == itr.index_; -} - -template -bool Iterator::operator!=(const Iterator& itr) const { - return !(*this == itr); -} - -template -bool Iterator::operator<(const Iterator& itr) const { - return index_ < itr.index_; -} - -template -bool Iterator::operator>(const Iterator& itr) const { - return index_ > itr.index_; -} - -template -bool Iterator::operator<=(const Iterator& itr) const { - return index_ <= itr.index_; -} - -template -bool Iterator::operator>=(const Iterator& itr) const { - return index_ >= itr.index_; +void BitInserter::insert_bits(uint8_t byte, size_t num_bits) { + size_t total_bits = num_bits + num_saved_bits_; + uint16_t new_value = saved_bits_ | (static_cast(byte) << num_saved_bits_); + if (total_bits >= 8) { + uint8_t new_byte = static_cast(new_value); + ByteInserter::insert_byte(new_byte); + total_bits -= 8; + new_value = new_value >> 8; + } + num_saved_bits_ = total_bits; + uint8_t mask = 0xff >> (8 - num_saved_bits_); + saved_bits_ = static_cast(new_value) & mask; } -template -uint8_t Iterator::operator*() const { - ASSERT_LOG(index_ < length_, "Index %zu out of bounds: %zu", index_, length_); - size_t index = index_; - - for (auto view : data_) { - if (index < view.size()) { - return view[index]; - } - index -= view.size(); - } - ASSERT_LOG(false, "Out of fragments searching for index %zu", index_); - return 0; +void BitInserter::insert_byte(uint8_t byte) { + insert_bits(byte, 8); } -template -size_t Iterator::NumBytesRemaining() const { - if (length_ > index_) { - return length_ - index_; - } else { - return 0; - } +bool BitInserter::IsByteAligned() { + return num_saved_bits_ == 0; } -// Explicit instantiations for both types of Iterators. -template class Iterator; -template class Iterator; } // namespace packet } // namespace bluetooth diff --git a/gd/packet/bit_inserter.h b/gd/packet/bit_inserter.h index 9034e38cd..2aa1ad60d 100644 --- a/gd/packet/bit_inserter.h +++ b/gd/packet/bit_inserter.h @@ -21,39 +21,21 @@ #include #include -#include "os/log.h" +#include "packet/byte_inserter.h" namespace bluetooth { namespace packet { -class BitInserter : public std::back_insert_iterator> { +class BitInserter : public ByteInserter { public: - BitInserter(std::vector& vector) : std::back_insert_iterator>(vector) {} - virtual ~BitInserter() { - ASSERT(num_saved_bits_ == 0); - } + BitInserter(std::vector& vector); + virtual ~BitInserter(); - void insert_bits(uint8_t byte, size_t num_bits) { - size_t total_bits = num_bits + num_saved_bits_; - uint16_t new_value = saved_bits_ | (static_cast(byte) << num_saved_bits_); - if (total_bits >= 8) { - uint8_t new_byte = static_cast(new_value); - std::back_insert_iterator>::operator=(new_byte); - total_bits -= 8; - new_value = new_value >> 8; - } - num_saved_bits_ = total_bits; - uint8_t mask = 0xff >> (8 - num_saved_bits_); - saved_bits_ = static_cast(new_value) & mask; - } + void insert_bits(uint8_t byte, size_t num_bits); - void insert_byte(uint8_t byte) { - insert_bits(byte, 8); - } + void insert_byte(uint8_t byte); - bool IsByteAligned() { - return num_saved_bits_ == 0; - } + bool IsByteAligned(); private: size_t num_saved_bits_{0}; diff --git a/gd/packet/bit_inserter_unittest.cc b/gd/packet/bit_inserter_unittest.cc index 6a3b66840..fae19f8ab 100644 --- a/gd/packet/bit_inserter_unittest.cc +++ b/gd/packet/bit_inserter_unittest.cc @@ -27,12 +27,6 @@ using std::vector; namespace bluetooth { namespace packet { -class BitInserterTest : public ::testing::Test { - public: - BitInserterTest() {} - ~BitInserterTest() = default; -}; - TEST(BitInserterTest, addMoreBits) { std::vector bytes; BitInserter it(bytes); @@ -41,12 +35,8 @@ TEST(BitInserterTest, addMoreBits) { it.insert_bits(static_cast(i), i); } it.insert_bits(static_cast(0b1010), 4); - std::vector result = { - 0b00011101 /* 3 2 1 */, - 0b00010101 /* 5 4 */, - 0b11100011 /* 7 6 */, - 0b10000000 /* 8 */, - 0b10100000 /* filled with 1010 */}; + std::vector result = {0b00011101 /* 3 2 1 */, 0b00010101 /* 5 4 */, 0b11100011 /* 7 6 */, 0b10000000 /* 8 */, + 0b10100000 /* filled with 1010 */}; ASSERT_EQ(result.size(), bytes.size()); for (size_t i = 0; i < bytes.size(); i++) { @@ -54,5 +44,39 @@ TEST(BitInserterTest, addMoreBits) { } } +TEST(BitInserterTest, observerTest) { + std::vector bytes; + BitInserter it(bytes); + std::vector copy; + + uint64_t checksum = 0x0123456789abcdef; + it.RegisterObserver(ByteObserver([©](uint8_t byte) { copy.push_back(byte); }, [checksum]() { return checksum; })); + + for (size_t i = 0; i < 9; i++) { + it.insert_bits(static_cast(i), i); + } + it.insert_bits(static_cast(0b1010), 4); + std::vector result = {0b00011101 /* 3 2 1 */, 0b00010101 /* 5 4 */, 0b11100011 /* 7 6 */, 0b10000000 /* 8 */, + 0b10100000 /* filled with 1010 */}; + + ASSERT_EQ(result.size(), bytes.size()); + for (size_t i = 0; i < bytes.size(); i++) { + ASSERT_EQ(result[i], bytes[i]); + } + + ASSERT_EQ(result.size(), copy.size()); + for (size_t i = 0; i < copy.size(); i++) { + ASSERT_EQ(result[i], copy[i]); + } + + ByteObserver observer = it.UnregisterObserver(); + ASSERT_EQ(checksum, observer.GetValue()); + uint8_t another_byte = 0xef; + it.insert_bits(another_byte, 8); + ASSERT_EQ(bytes.back(), another_byte); + ASSERT_EQ(result.size() + 1, bytes.size()); + ASSERT_EQ(result.size(), copy.size()); +} + } // namespace packet } // namespace bluetooth diff --git a/gd/packet/byte_inserter.cc b/gd/packet/byte_inserter.cc new file mode 100644 index 000000000..f7fc9c02e --- /dev/null +++ b/gd/packet/byte_inserter.cc @@ -0,0 +1,48 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "packet/byte_inserter.h" + +#include "os/log.h" + +namespace bluetooth { +namespace packet { + +ByteInserter::ByteInserter(std::vector& vector) : std::back_insert_iterator>(vector) {} + +ByteInserter::~ByteInserter() { + ASSERT(registered_observers_.size() == 0); +} + +void ByteInserter::RegisterObserver(ByteObserver observer) { + registered_observers_.push_back(observer); +} + +ByteObserver ByteInserter::UnregisterObserver() { + ByteObserver observer = registered_observers_.back(); + registered_observers_.pop_back(); + return observer; +} + +void ByteInserter::insert_byte(uint8_t byte) { + for (auto& observer : registered_observers_) { + observer.OnByte(byte); + } + std::back_insert_iterator>::operator=(byte); +} + +} // namespace packet +} // namespace bluetooth diff --git a/gd/packet/byte_inserter.h b/gd/packet/byte_inserter.h new file mode 100644 index 000000000..2d49b339c --- /dev/null +++ b/gd/packet/byte_inserter.h @@ -0,0 +1,45 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +#include "packet/byte_observer.h" + +namespace bluetooth { +namespace packet { + +class ByteInserter : public std::back_insert_iterator> { + public: + ByteInserter(std::vector& vector); + virtual ~ByteInserter(); + + void insert_byte(uint8_t byte); + + void RegisterObserver(ByteObserver observer); + + ByteObserver UnregisterObserver(); + + private: + std::vector registered_observers_; +}; + +} // namespace packet +} // namespace bluetooth diff --git a/gd/packet/byte_observer.cc b/gd/packet/byte_observer.cc new file mode 100644 index 000000000..358a230b5 --- /dev/null +++ b/gd/packet/byte_observer.cc @@ -0,0 +1,34 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "packet/byte_observer.h" + +namespace bluetooth { +namespace packet { + +ByteObserver::ByteObserver(const std::function& on_byte, const std::function& get_value) + : on_byte_(on_byte), get_value_(get_value) {} + +void ByteObserver::OnByte(uint8_t byte) { + on_byte_(byte); +} + +uint64_t ByteObserver::GetValue() { + return get_value_(); +} + +} // namespace packet +} // namespace bluetooth diff --git a/gd/packet/byte_observer.h b/gd/packet/byte_observer.h new file mode 100644 index 000000000..adfcfc1bb --- /dev/null +++ b/gd/packet/byte_observer.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace bluetooth { +namespace packet { + +class ByteObserver { + public: + ByteObserver(const std::function& on_byte_, const std::function& get_value_); + + void OnByte(uint8_t byte); + + uint64_t GetValue(); + + private: + std::function on_byte_; + std::function get_value_; +}; + +} // namespace packet +} // namespace bluetooth -- 2.11.0