comparison 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
comparison
equal deleted inserted replaced
363:f10507d8f686 364:99c961c91809
1 #include "sys/x11/settings.h" 1 #include "sys/x11/settings.h"
2 #include "core/endian.h" 2 #include "core/byte_stream.h"
3 3
4 #include <cassert>
4 #include <cstring> 5 #include <cstring>
5 #include <cstdint> 6 #include <cstdint>
6 #include <climits> 7 #include <climits>
7 #include <string_view> 8 #include <string_view>
8 #include <memory> 9 #include <memory>
9 #include <array> 10 #include <array>
10 #include <optional> 11 #include <optional>
11 #include <iostream>
12 #include <map> 12 #include <map>
13 13
14 #include <xcb/xcb.h> 14 #include <xcb/xcb.h>
15 15
16 #include "fmt/core.h" 16 #include "fmt/core.h"
38 38
39 class Parser { 39 class Parser {
40 public: 40 public:
41 Parser(std::uint8_t *bytes, std::size_t size); 41 Parser(std::uint8_t *bytes, std::size_t size);
42 42
43 std::vector<SettingsItem> ParseAllItems(void); 43 bool ParseHeader(void);
44 std::optional<SettingsItem> ParseNextItem(void); 44 std::optional<SettingsItem> ParseNextItem(void);
45 45
46 std::uint32_t GetTotalItems(void); 46 std::uint32_t GetTotalItems(void);
47 47
48 private: 48 private:
49 /* byte order values */ 49 enum ByteOrder {
50 enum {
51 LSBFirst = 0, 50 LSBFirst = 0,
52 MSBFirst = 1, 51 MSBFirst = 1,
53 }; 52 };
54 53
55 template<typename T> 54 ByteStream stream;
56 bool ReadData(T& ret) {
57 if (offset_ + sizeof(T) >= size_)
58 return false;
59
60 ret = *reinterpret_cast<T*>(bytes_ + offset_);
61 Advance(sizeof(T));
62 return true;
63 }
64
65 /* will fail on signed integers; xsettings has none of those though */
66 template<typename T>
67 bool ReadInt(T& ret) {
68 static_assert(std::is_integral<T>::value);
69
70 if (!ReadData<T>(ret))
71 return false;
72
73 switch (byte_order_) {
74 case LSBFirst:
75 ret = Endian::byteswap_little_to_host(ret);
76 break;
77 case MSBFirst:
78 ret = Endian::byteswap_big_to_host(ret);
79 break;
80 default:
81 /* can't know for sure. punt */
82 return false;
83 }
84
85 return true;
86 }
87
88 bool ReadString(std::string& str, std::size_t size);
89 bool Advance(std::size_t amount);
90
91 /* raw data */
92 std::uint8_t *bytes_ = nullptr;
93 std::size_t offset_ = 0;
94 std::size_t size_ = 0;
95 55
96 /* parsed in the constructor */ 56 /* parsed in the constructor */
97 std::uint8_t byte_order_ = 0;
98 std::uint32_t serial_ = 0; 57 std::uint32_t serial_ = 0;
99 std::uint32_t total_items_ = 0; 58 std::uint32_t total_items_ = 0;
100 }; 59 };
101 60
102 std::uint32_t Parser::GetTotalItems(void) { 61 std::uint32_t Parser::GetTotalItems(void) {
103 return total_items_; 62 return total_items_;
104 } 63 }
105 64
106 bool Parser::ReadString(std::string& str, std::size_t size) { 65 Parser::Parser(std::uint8_t *bytes, std::size_t size) : stream(bytes, size) {
107 if (offset_ + size >= size_) 66 }
108 return false; 67
109 68 bool Parser::ParseHeader(void) {
110 str.assign(reinterpret_cast<const char *>(bytes_ + offset_), size); 69 std::uint8_t byte_order;
111 Advance(size); 70 if (!stream.ReadBinary<std::uint8_t>(byte_order))
71 return false;
72
73 switch (byte_order) {
74 case MSBFirst:
75 stream.SetEndianness(ByteStream::ByteOrder::Big);
76 break;
77 case LSBFirst:
78 stream.SetEndianness(ByteStream::ByteOrder::Little);
79 break;
80 default:
81 return false; /* errr */
82 }
83
84 stream.Advance(3);
85
86 if (!stream.ReadInt<std::uint32_t>(serial_))
87 return false;
88
89 if (!stream.ReadInt<std::uint32_t>(total_items_))
90 return false;
91
112 return true; 92 return true;
113 }
114
115 bool Parser::Advance(std::size_t amount) {
116 if (offset_ + amount >= size_)
117 return false;
118
119 offset_ += amount;
120 return true;
121 }
122
123 Parser::Parser(std::uint8_t *bytes, std::size_t size) {
124 bytes_ = bytes;
125 size_ = size;
126
127 if (!ReadData<std::uint8_t>(byte_order_))
128 return;
129
130 Advance(3);
131
132 if (!ReadInt<std::uint32_t>(serial_))
133 return;
134
135 if (!ReadInt<std::uint32_t>(total_items_))
136 return;
137 } 93 }
138 94
139 std::optional<SettingsItem> Parser::ParseNextItem(void) { 95 std::optional<SettingsItem> Parser::ParseNextItem(void) {
140 SettingsItem item; 96 SettingsItem item;
141 97
142 /* read one byte */ 98 /* read one byte */
143 if (!ReadInt<std::uint8_t>(item.type)) 99 if (!stream.ReadInt<std::uint8_t>(item.type))
144 return std::nullopt; 100 return std::nullopt;
145 101
146 if (!item.VerifyType()) 102 if (!item.VerifyType())
147 return std::nullopt; 103 return std::nullopt;
148 104
149 /* skip padding */ 105 /* skip padding */
150 if (!Advance(1)) 106 if (!stream.Advance(1))
151 return std::nullopt; 107 return std::nullopt;
152 108
153 /* parse the name */ 109 /* parse the name */
154 std::uint16_t name_size; 110 std::uint16_t name_size;
155 if (!ReadInt<std::uint16_t>(name_size)) 111 if (!stream.ReadInt<std::uint16_t>(name_size))
156 return std::nullopt; 112 return std::nullopt;
157 113
158 if (!ReadString(item.name, name_size)) 114 if (!stream.ReadString(item.name, name_size))
159 return std::nullopt; 115 return std::nullopt;
160 116
161 /* padding */ 117 /* padding */
162 if (!Advance(GetPadding(name_size, 4))) 118 if (!stream.Advance(GetPadding(name_size, 4)))
163 return std::nullopt; 119 return std::nullopt;
164 120
165 if (!ReadInt<std::uint32_t>(item.serial)) 121 if (!stream.ReadInt<std::uint32_t>(item.serial))
166 return std::nullopt; 122 return std::nullopt;
167 123
168 switch (item.type) { 124 switch (item.type) {
169 case SettingsItem::TypeInt: { 125 case SettingsItem::TypeInt: {
170 if (!ReadInt<std::uint32_t>(item.data.integer)) 126 if (!stream.ReadInt<std::int32_t>(item.data.integer))
171 return std::nullopt; 127 return std::nullopt;
172 128
173 break; 129 break;
174 } 130 }
175 case SettingsItem::TypeStr: { 131 case SettingsItem::TypeStr: {
176 std::uint32_t size; 132 std::uint32_t size;
177 if (!ReadInt<std::uint32_t>(size)) 133 if (!stream.ReadInt<std::uint32_t>(size))
178 return std::nullopt; 134 return std::nullopt;
179 135
180 if (!ReadString(item.data.string, size)) 136 if (!stream.ReadString(item.data.string, size))
181 return std::nullopt; 137 return std::nullopt;
182 138
183 /* padding */ 139 /* don't fail if advancing fails on this padding,
184 if (!Advance(GetPadding(size, 4))) 140 * because this causes parsing to fail for strings
185 return std::nullopt; 141 * at the end of the data */
142 stream.Advance(GetPadding(size, 4));
186 143
187 break; 144 break;
188 } 145 }
189 case SettingsItem::TypeRgba: { 146 case SettingsItem::TypeRgba: {
190 /* The order here is important!! */ 147 /* it's actually RBGA, but whatever. */
191 if (!ReadInt<std::uint16_t>(item.data.rgba.red) 148 if (!stream.ReadInt<std::uint16_t>(item.data.rgba.red)
192 || !ReadInt<std::uint16_t>(item.data.rgba.blue) 149 || !stream.ReadInt<std::uint16_t>(item.data.rgba.blue)
193 || !ReadInt<std::uint16_t>(item.data.rgba.green) 150 || !stream.ReadInt<std::uint16_t>(item.data.rgba.green)
194 || !ReadInt<std::uint16_t>(item.data.rgba.alpha)) 151 || !stream.ReadInt<std::uint16_t>(item.data.rgba.alpha))
195 return std::nullopt; 152 return std::nullopt;
196 153
197 break; 154 break;
198 } 155 }
199 default: 156 default:
200 /* can't do anything now, can we? */ 157 /* can't do anything now, can we? */
201 return std::nullopt; 158 return std::nullopt;
202 } 159 }
203 160
204 return item; 161 return item;
205 }
206
207 std::vector<SettingsItem> Parser::ParseAllItems(void) {
208 offset_ = 0;
209
210 std::uint32_t i;
211 std::vector<SettingsItem> items;
212
213 for (i = 0; i < total_items_; i++) {
214 std::optional<SettingsItem> item = ParseNextItem();
215 if (!item)
216 break;
217
218 items.push_back(item.value());
219 }
220
221 return items;
222 } 162 }
223 163
224 /* ------------------------------------------------------------------------- */ 164 /* ------------------------------------------------------------------------- */
225 /* real X11 code */ 165 /* real X11 code */
226 166
321 std::vector<std::uint8_t> xsettings_raw; 261 std::vector<std::uint8_t> xsettings_raw;
322 if (!GetRawSettingsData(xsettings_raw)) 262 if (!GetRawSettingsData(xsettings_raw))
323 return false; 263 return false;
324 264
325 Parser parser(xsettings_raw.data(), xsettings_raw.size()); 265 Parser parser(xsettings_raw.data(), xsettings_raw.size());
326 settings = parser.ParseAllItems(); 266 if (!parser.ParseHeader())
267 return false;
268
269 std::uint32_t total = parser.GetTotalItems();
270
271 while (total--) {
272 std::optional<SettingsItem> opt_item = parser.ParseNextItem();
273 if (!opt_item)
274 break;
275
276 settings.push_back(opt_item.value());
277 }
327 278
328 return true; 279 return true;
329 } 280 }
330 281
331 bool FindSetting(const std::string& name, SettingsItem& setting) { 282 bool FindSetting(const std::string& name, SettingsItem& setting) {
332 std::vector<std::uint8_t> xsettings_raw; 283 std::vector<std::uint8_t> xsettings_raw;
333 if (!GetRawSettingsData(xsettings_raw)) 284 if (!GetRawSettingsData(xsettings_raw))
334 return false; 285 return false;
335 286
336 Parser parser(xsettings_raw.data(), xsettings_raw.size()); 287 Parser parser(xsettings_raw.data(), xsettings_raw.size());
288 if (!parser.ParseHeader())
289 return false;
337 290
338 std::uint32_t total = parser.GetTotalItems(); 291 std::uint32_t total = parser.GetTotalItems();
339 292
340 for (; total; total--) { 293 while (total--) {
341 std::optional<SettingsItem> opt_item = parser.ParseNextItem(); 294 std::optional<SettingsItem> opt_item = parser.ParseNextItem();
342 if (!opt_item) 295 if (!opt_item)
343 return false; 296 return false;
344 297
345 SettingsItem& item = opt_item.value(); 298 SettingsItem& item = opt_item.value();