Mercurial > minori
diff src/sys/x11/settings.cc @ 364:99c961c91809
core: refactor out byte stream into its own file
easy dubs
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Tue, 16 Jul 2024 21:15:59 -0400 |
parents | 9aaf1e788896 |
children |
line wrap: on
line diff
--- a/src/sys/x11/settings.cc Mon Jul 15 01:33:51 2024 -0400 +++ b/src/sys/x11/settings.cc Tue Jul 16 21:15:59 2024 -0400 @@ -1,6 +1,7 @@ #include "sys/x11/settings.h" -#include "core/endian.h" +#include "core/byte_stream.h" +#include <cassert> #include <cstring> #include <cstdint> #include <climits> @@ -8,7 +9,6 @@ #include <memory> #include <array> #include <optional> -#include <iostream> #include <map> #include <xcb/xcb.h> @@ -40,61 +40,20 @@ public: Parser(std::uint8_t *bytes, std::size_t size); - std::vector<SettingsItem> ParseAllItems(void); + bool ParseHeader(void); std::optional<SettingsItem> ParseNextItem(void); std::uint32_t GetTotalItems(void); private: - /* byte order values */ - enum { + enum ByteOrder { LSBFirst = 0, MSBFirst = 1, }; - template<typename T> - bool ReadData(T& ret) { - if (offset_ + sizeof(T) >= size_) - return false; - - ret = *reinterpret_cast<T*>(bytes_ + offset_); - Advance(sizeof(T)); - return true; - } - - /* will fail on signed integers; xsettings has none of those though */ - template<typename T> - bool ReadInt(T& ret) { - static_assert(std::is_integral<T>::value); - - if (!ReadData<T>(ret)) - return false; - - switch (byte_order_) { - case LSBFirst: - ret = Endian::byteswap_little_to_host(ret); - break; - case MSBFirst: - ret = Endian::byteswap_big_to_host(ret); - break; - default: - /* can't know for sure. punt */ - return false; - } - - return true; - } - - bool ReadString(std::string& str, std::size_t size); - bool Advance(std::size_t amount); - - /* raw data */ - std::uint8_t *bytes_ = nullptr; - std::size_t offset_ = 0; - std::size_t size_ = 0; + ByteStream stream; /* parsed in the constructor */ - std::uint8_t byte_order_ = 0; std::uint32_t serial_ = 0; std::uint32_t total_items_ = 0; }; @@ -103,95 +62,93 @@ return total_items_; } -bool Parser::ReadString(std::string& str, std::size_t size) { - if (offset_ + size >= size_) - return false; - - str.assign(reinterpret_cast<const char *>(bytes_ + offset_), size); - Advance(size); - return true; +Parser::Parser(std::uint8_t *bytes, std::size_t size) : stream(bytes, size) { } -bool Parser::Advance(std::size_t amount) { - if (offset_ + amount >= size_) +bool Parser::ParseHeader(void) { + std::uint8_t byte_order; + if (!stream.ReadBinary<std::uint8_t>(byte_order)) return false; - offset_ += amount; - return true; -} - -Parser::Parser(std::uint8_t *bytes, std::size_t size) { - bytes_ = bytes; - size_ = size; + switch (byte_order) { + case MSBFirst: + stream.SetEndianness(ByteStream::ByteOrder::Big); + break; + case LSBFirst: + stream.SetEndianness(ByteStream::ByteOrder::Little); + break; + default: + return false; /* errr */ + } - if (!ReadData<std::uint8_t>(byte_order_)) - return; + stream.Advance(3); - Advance(3); + if (!stream.ReadInt<std::uint32_t>(serial_)) + return false; - if (!ReadInt<std::uint32_t>(serial_)) - return; + if (!stream.ReadInt<std::uint32_t>(total_items_)) + return false; - if (!ReadInt<std::uint32_t>(total_items_)) - return; + return true; } std::optional<SettingsItem> Parser::ParseNextItem(void) { SettingsItem item; /* read one byte */ - if (!ReadInt<std::uint8_t>(item.type)) + if (!stream.ReadInt<std::uint8_t>(item.type)) return std::nullopt; if (!item.VerifyType()) return std::nullopt; /* skip padding */ - if (!Advance(1)) + if (!stream.Advance(1)) return std::nullopt; /* parse the name */ std::uint16_t name_size; - if (!ReadInt<std::uint16_t>(name_size)) + if (!stream.ReadInt<std::uint16_t>(name_size)) return std::nullopt; - if (!ReadString(item.name, name_size)) + if (!stream.ReadString(item.name, name_size)) return std::nullopt; /* padding */ - if (!Advance(GetPadding(name_size, 4))) + if (!stream.Advance(GetPadding(name_size, 4))) return std::nullopt; - if (!ReadInt<std::uint32_t>(item.serial)) + if (!stream.ReadInt<std::uint32_t>(item.serial)) return std::nullopt; switch (item.type) { case SettingsItem::TypeInt: { - if (!ReadInt<std::uint32_t>(item.data.integer)) + if (!stream.ReadInt<std::int32_t>(item.data.integer)) return std::nullopt; break; } case SettingsItem::TypeStr: { std::uint32_t size; - if (!ReadInt<std::uint32_t>(size)) + if (!stream.ReadInt<std::uint32_t>(size)) return std::nullopt; - if (!ReadString(item.data.string, size)) + if (!stream.ReadString(item.data.string, size)) return std::nullopt; - /* padding */ - if (!Advance(GetPadding(size, 4))) - return std::nullopt; + /* don't fail if advancing fails on this padding, + * because this causes parsing to fail for strings + * at the end of the data */ + stream.Advance(GetPadding(size, 4)); break; } case SettingsItem::TypeRgba: { - /* The order here is important!! */ - if (!ReadInt<std::uint16_t>(item.data.rgba.red) - || !ReadInt<std::uint16_t>(item.data.rgba.blue) - || !ReadInt<std::uint16_t>(item.data.rgba.green) - || !ReadInt<std::uint16_t>(item.data.rgba.alpha)) + /* it's actually RBGA, but whatever. */ + if (!stream.ReadInt<std::uint16_t>(item.data.rgba.red) + || !stream.ReadInt<std::uint16_t>(item.data.rgba.blue) + || !stream.ReadInt<std::uint16_t>(item.data.rgba.green) + || !stream.ReadInt<std::uint16_t>(item.data.rgba.alpha)) return std::nullopt; break; @@ -204,23 +161,6 @@ return item; } -std::vector<SettingsItem> Parser::ParseAllItems(void) { - offset_ = 0; - - std::uint32_t i; - std::vector<SettingsItem> items; - - for (i = 0; i < total_items_; i++) { - std::optional<SettingsItem> item = ParseNextItem(); - if (!item) - break; - - items.push_back(item.value()); - } - - return items; -} - /* ------------------------------------------------------------------------- */ /* real X11 code */ @@ -323,7 +263,18 @@ return false; Parser parser(xsettings_raw.data(), xsettings_raw.size()); - settings = parser.ParseAllItems(); + if (!parser.ParseHeader()) + return false; + + std::uint32_t total = parser.GetTotalItems(); + + while (total--) { + std::optional<SettingsItem> opt_item = parser.ParseNextItem(); + if (!opt_item) + break; + + settings.push_back(opt_item.value()); + } return true; } @@ -334,10 +285,12 @@ return false; Parser parser(xsettings_raw.data(), xsettings_raw.size()); + if (!parser.ParseHeader()) + return false; std::uint32_t total = parser.GetTotalItems(); - for (; total; total--) { + while (total--) { std::optional<SettingsItem> opt_item = parser.ParseNextItem(); if (!opt_item) return false;