Implement BinaryWriter class to allow writing binary data
This commit is contained in:
parent
ee38b6a181
commit
c5f1a2724b
5 changed files with 265 additions and 0 deletions
|
|
@ -79,6 +79,7 @@ set(SOURCES
|
|||
anbox/common/loop_device.cpp
|
||||
anbox/common/loop_device_allocator.cpp
|
||||
anbox/common/mount_entry.cpp
|
||||
anbox/common/binary_writer.cpp
|
||||
|
||||
anbox/testing/gtest_utils.h
|
||||
|
||||
|
|
|
|||
106
src/anbox/common/binary_writer.cpp
Normal file
106
src/anbox/common/binary_writer.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Thomas Voss <thomas.voss.bochum@gmail.com>
|
||||
* Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/common/binary_writer.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
namespace {
|
||||
bool is_little_endian() {
|
||||
std::uint32_t v = 1;
|
||||
return (*reinterpret_cast<std::uint8_t*>(&v) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace common {
|
||||
|
||||
BinaryWriter::BinaryWriter(std::vector<std::uint8_t>::iterator begin,
|
||||
std::vector<std::uint8_t>::iterator end) :
|
||||
begin_{begin}, current_{begin}, end_{end},
|
||||
byte_order_{is_little_endian() ? Order::Little : Order::Big} {}
|
||||
|
||||
void BinaryWriter::set_byte_order(Order order) {
|
||||
byte_order_ = order;
|
||||
}
|
||||
|
||||
void BinaryWriter::write_unsigned_short(std::uint16_t value) {
|
||||
if (current_ + sizeof(value) > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
std::uint16_t v = value;
|
||||
switch (byte_order_) {
|
||||
case Order::Big:
|
||||
v = boost::endian::native_to_big(value);
|
||||
break;
|
||||
case Order::Little:
|
||||
v = boost::endian::native_to_little(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*reinterpret_cast<std::uint16_t*>(&(*current_)) = v;
|
||||
current_ += sizeof(v);
|
||||
}
|
||||
|
||||
void BinaryWriter::write_unsigned_long(std::uint32_t value) {
|
||||
if (current_ + sizeof(value) > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
std::uint32_t v = value;
|
||||
switch (byte_order_) {
|
||||
case Order::Big:
|
||||
v = boost::endian::native_to_big(value);
|
||||
break;
|
||||
case Order::Little:
|
||||
v = boost::endian::native_to_little(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*reinterpret_cast<std::uint32_t*>(&(*current_)) = v;
|
||||
current_ += sizeof(v);
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string(const char *s, std::size_t size) {
|
||||
if (current_ + size > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
memcpy(&(*current_), s, size);
|
||||
current_ += size;
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string_with_size(const std::string &str) {
|
||||
write_string_with_size(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string_with_size(const char *s, std::size_t size) {
|
||||
write_unsigned_short(size);
|
||||
write_string(s, size);
|
||||
}
|
||||
|
||||
std::size_t BinaryWriter::bytes_written() const {
|
||||
return current_ - begin_;
|
||||
}
|
||||
} // namespace common
|
||||
} // namespace anbox
|
||||
57
src/anbox/common/binary_writer.h
Normal file
57
src/anbox/common/binary_writer.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Thomas Voss <thomas.voss.bochum@gmail.com>
|
||||
* Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_COMMON_BINARY_WRITER_H_
|
||||
#define ANBOX_COMMON_BINARY_WRITER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace common {
|
||||
class BinaryWriter {
|
||||
public:
|
||||
enum class Order {
|
||||
Big,
|
||||
Little,
|
||||
};
|
||||
|
||||
explicit BinaryWriter(std::vector<std::uint8_t>::iterator begin_,
|
||||
std::vector<std::uint8_t>::iterator end_);
|
||||
|
||||
void set_byte_order(Order order);
|
||||
|
||||
void write_unsigned_short(std::uint16_t value);
|
||||
void write_unsigned_long(std::uint32_t value);
|
||||
void write_string(const char *s, std::size_t size);
|
||||
void write_string_with_size(const std::string &str);
|
||||
void write_string_with_size(const char *s, std::size_t size);
|
||||
|
||||
std::size_t bytes_written() const;
|
||||
|
||||
private:
|
||||
std::vector<std::uint8_t>::iterator begin_;
|
||||
std::vector<std::uint8_t>::iterator current_;
|
||||
std::vector<std::uint8_t>::iterator end_;
|
||||
Order byte_order_;
|
||||
};
|
||||
} // namespace common
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -2,3 +2,4 @@ ANBOX_ADD_TEST(message_channel_tests message_channel_tests.cpp)
|
|||
ANBOX_ADD_TEST(small_vector_tests small_vector_tests.cpp)
|
||||
ANBOX_ADD_TEST(type_traits_tests type_traits_tests.cpp)
|
||||
ANBOX_ADD_TEST(scope_ptr_tests scope_ptr_tests.cpp)
|
||||
ANBOX_ADD_TEST(binary_writer_tests binary_writer_tests.cpp)
|
||||
|
|
|
|||
100
tests/anbox/common/binary_writer_tests.cpp
Normal file
100
tests/anbox/common/binary_writer_tests.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/common/binary_writer.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
namespace ac = anbox::common;
|
||||
|
||||
using namespace ::testing;
|
||||
|
||||
TEST(BinaryWriter, WritesUnsignedLong) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
buffer.resize(sizeof(std::uint32_t) * 2);
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
|
||||
writer.write_unsigned_long(0x10);
|
||||
writer.write_unsigned_long(0x3322);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x10, 0x00, 0x00, 0x00, 0x22, 0x33, 0x00, 0x00));
|
||||
}
|
||||
|
||||
TEST(BinaryWriter, WriteUnsignedLongFailsWithExhaustedError) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
EXPECT_THROW(writer.write_unsigned_long(0x11), std::out_of_range);
|
||||
}
|
||||
|
||||
TEST(BinaryWriter, WriteUnsignedLongWithChangedBinaryOrder) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
buffer.resize(sizeof(std::uint32_t));
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
|
||||
writer.set_byte_order(ac::BinaryWriter::Order::Big);
|
||||
writer.write_unsigned_long(0x11223344);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x11, 0x22, 0x33, 0x44));
|
||||
|
||||
buffer.clear();
|
||||
buffer.resize(sizeof(std::uint32_t));
|
||||
|
||||
writer = ac::BinaryWriter(buffer.begin(), buffer.end());
|
||||
|
||||
writer.set_byte_order(ac::BinaryWriter::Order::Little);
|
||||
writer.write_unsigned_long(0x11223344);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x44, 0x33, 0x22, 0x11));
|
||||
}
|
||||
|
||||
TEST(BinaryWriter, WriteUnsignedShort) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
buffer.resize(sizeof(std::uint16_t) * 2);
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
|
||||
writer.write_unsigned_short(0x10);
|
||||
writer.write_unsigned_short(0x3322);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x10, 0x00, 0x22, 0x33));
|
||||
}
|
||||
|
||||
TEST(BinaryWriter, WriteUnsignedShortFailsWithExhaustedError) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
EXPECT_THROW(writer.write_unsigned_short(0x11), std::out_of_range);
|
||||
}
|
||||
|
||||
TEST(BinaryWriter, WriteUnsignedShortWithChangedBinaryOrder) {
|
||||
std::vector<std::uint8_t> buffer;
|
||||
buffer.resize(sizeof(std::uint16_t));
|
||||
ac::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
|
||||
writer.set_byte_order(ac::BinaryWriter::Order::Big);
|
||||
writer.write_unsigned_short(0x1122);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x11, 0x22));
|
||||
|
||||
buffer.clear();
|
||||
buffer.resize(sizeof(std::uint16_t));
|
||||
|
||||
writer = ac::BinaryWriter(buffer.begin(), buffer.end());
|
||||
|
||||
writer.set_byte_order(ac::BinaryWriter::Order::Little);
|
||||
writer.write_unsigned_short(0x1122);
|
||||
|
||||
ASSERT_THAT(buffer, ElementsAre(0x22, 0x11));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue