main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "crucible/boba/metadata.hpp" #include <cstdlib> #include <iomanip> #include <iostream> #include <optional> #include <string> #include <vector> #ifdef CRUCIBLE_UNIX #include "crucible/unix/fs.hpp" namespace platform_fs = crucible::unix::fs; #endif #ifdef CRUCIBLE_WINDOWS #include "crucible/windows/fs.hpp" namespace platform_fs = crucible::windows::fs; #endif [[nodiscard]] auto read_boba_container(std::string const &boba_file_path) -> std::optional<crucible::boba::metadata::Container> { auto const is_file_result = platform_fs::is_file(boba_file_path); if (is_file_result.has_lhs()) { std::cerr << "Filesystem error: " << is_file_result.get_lhs().format() << "\n"; return std::nullopt; } bool const is_file = is_file_result.get_rhs(); if (!is_file) { std::cerr << "Path '" << boba_file_path << "' does not refer to a regular file\n"; return std::nullopt; } auto read_file_data_result = platform_fs::read_file_data(boba_file_path); if (read_file_data_result.has_lhs()) { std::cerr << "Filesystem error: " << read_file_data_result.get_lhs().format() << "\n"; return std::nullopt; } auto const file_contents = std::move(read_file_data_result).get_rhs(); auto from_bytes_result = crucible::boba::metadata::from_bytes(file_contents); if (from_bytes_result.has_lhs()) { std::cerr << "Failed to parse BOBA metadata: " << from_bytes_result.get_lhs().format() << "\n"; return std::nullopt; } return std::move(from_bytes_result).get_rhs(); } auto dump_boba_container(crucible::boba::metadata::Container const &metadata) -> void { auto const schema = metadata.get_schema(); std::cout << "• Schema block:\n" << " • Full header count: " << schema.get_full_header_count() << "\n" << " • User header count: " << schema.get_user_header_count() << "\n" << " • Size of each header: " << schema.get_header_size() << " bytes\n" << " • Schema entry count: " << schema.get_entry_count() << "\n" << " • Size of each schema entry: " << schema.get_entry_size() << " bytes\n"; std::cout << "\n"; std::size_t index = 0; for (const auto &header : metadata) { std::cout << "• User block " << index << ":\n"; std::cout << " • Signature: 0x" << std::hex << header.signature << std::dec << "\n" << " • Data size: " << header.data_size << " bytes\n" << " • User data[0]: 0x" << std::hex << header.user_data[0] << std::dec << "\n" << " • User data[1]: 0x" << std::hex << header.user_data[1] << std::dec << "\n" << " • Data starts at offset: " << header.offset << "\n"; ++index; } } auto main(int argc, char *argv[]) -> int { std::vector<std::string> const arguments(argv + 1, argv + argc); std::optional<std::string> boba_file_path {}; auto current = arguments.begin(); auto const end = arguments.end(); while (current != end) { if (!boba_file_path.has_value()) { boba_file_path = *current++; continue; } std::cerr << "Unrecognized option or argument '" << *current << "'\n" << "Usage: " << argv[0] << " BOBA_FILE\n"; return EXIT_FAILURE; } if (!boba_file_path.has_value()) { std::cerr << "Missing argument BOBA_FILE\n" << "Usage: " << argv[0] << " BOBA_FILE\n"; return EXIT_FAILURE; } auto const container = read_boba_container(boba_file_path.value()); if (!container.has_value()) { std::cerr << "Usage: " << argv[0] << " BOBA_FILE\n"; return EXIT_FAILURE; } dump_boba_container(container.value()); return EXIT_SUCCESS; }