提交 c5f1a272 编写于 作者: S Simon Fels

Implement BinaryWriter class to allow writing binary data

上级 ee38b6a1
......@@ -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
......
/*
* 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
/*
* 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)
/*
* 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));
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册