wowlib 0.0.0
Read & write World of Warcraft client files — a C++26 core
Loading...
Searching...
No Matches
table.hpp
Go to the documentation of this file.
1#pragma once
2
21
22#include <cstddef>
23#include <cstdint>
24#include <span>
25#include <string_view>
26#include <vector>
27
28#include <welder/vocabulary.hpp>
29
32#include <wowlib/core/error.hpp>
34#include <wowlib/db/codec.hpp>
36#include <wowlib/db/schema.hpp>
41
42namespace wowlib::db {
50 template <TableRecord Record>
51 class Table {
52 public:
54 static constexpr ClientVersion Version = Record::Version;
55
57 static constexpr std::string_view TableName = Record::TableName;
58
59 [[=welder::mark::no_reassign,
60 =welder::doc("The decoded records, file order. Mutate in place; write() "
61 "serializes exactly this list.")]]
62 std::vector<Record> records;
64 Table() { _wire(); }
65 Table(const Table& o) : records{o.records}, _core{o._core} { _wire(); }
66
67 Table(Table&& o) noexcept : records{std::move(o.records)}, _core{std::move(o._core)} {
68 _wire();
69 }
70
71 Table& operator=(const Table& o) {
72 records = o.records;
73 _core = o._core;
74 _wire();
75 return *this;
76 }
77
78 Table& operator=(Table&& o) noexcept {
79 records = std::move(o.records);
80 _core = std::move(o._core);
81 _wire();
82 return *this;
83 }
84
88 [[=welder::doc("Decode a table file image."),
89 =welder::returns(
90 "nothing; raises on malformed input or a schema mismatch")]]
91 Result<void> read(std::span<const std::byte> data [[=welder::doc("the whole file content")]]) {
92 return _core.read(data);
93 }
94
98 @return nothing, or why loading failed. */
99 Result<void> read(fs::FileSystem& fs [[=welder::doc("the filesystem gateway")]],
100 const FileKey& key [[=welder::doc("the file to read")]]) {
101 return _core.read(fs, key);
102 }
103
109 [[=welder::doc(
110 "Serialize the table to a file image; a loaded table re-emits "
111 "the format it was read from. `policy` decides how keyless "
112 "encrypted sections are handled."),
113 =welder::returns("the file bytes")]]
115 [[=welder::doc("keyless-section handling (WDC only)")]]
117 return _core.write(policy);
118 }
119
123 @param policy how keyless encrypted sections are handled (see write()).
124 @return nothing, or why saving failed. */
125 Result<void> write(fs::FileSystem& fs [[=welder::doc("the filesystem gateway")]],
126 const FileKey& key [[=welder::doc("the file to write")]],
127 EncryptedPolicy policy
128 [[=welder::doc("keyless-section handling (WDC only)")]]
130 return _core.write(fs, key, policy);
131 }
132
135 [[=welder::getter,
136 =welder::doc(
137 "The preserved string block the record string fields were decoded "
138 "from; offsets never move, write() appends new strings past its "
139 "end.")]]
140 const formats::StringBlock& strings() const { return _core.strings(); }
141
143
145 [[=welder::getter,
146 =welder::doc(
147 "The encrypted sections skipped on read: their records are not "
148 "in records, but the file re-writes them verbatim.")]]
149 const std::vector<EncryptedSection>& encryptedSections() const {
150 return _core.encryptedSections();
151 }
152
155 [[=welder::getter,
156 =welder::doc(
157 "Whether the whole table decoded — false when encrypted sections "
158 "were skipped.")]]
159 bool fullyDecoded() const { return _core.fullyDecoded(); }
160
161 // There is deliberately NO "value fits its column" check: a column's width
162 // IS its member's width (schema.hpp derives one from the other) and the WDC
163 // writer sizes each bit-packed field from the actual value range it is
164 // given, so nothing reachable through the typed API can overflow what
165 // encodes it.
166 [[nodiscard]]
167 [[=welder::doc(R"(
168 Check the logical integrity contracts the records must satisfy to
169 survive a write and load in the client: the primary key stays unique,
170 and no string holds an embedded NUL the string block would truncate.
171 write() never runs this.)"),
172 =welder::returns("every violated contract, in record order")]]
173 formats::ValidationReport validate() const { return _core.validate(); }
174
175 [[nodiscard]]
176 [[=welder::doc("Validate and raise on the first error instead of returning "
177 "a report — the assert-style face of validate()."),
178 =welder::returns("nothing; raises when validate() finds any error")]]
179 Result<void> ensureValid() const { return validate().toResult(); }
180
182 const TableCore& core() const { return _core; }
183
184 private:
186 void _wire() {
187 static constexpr auto Schema = schemaOf<Record>();
188 _core.wire(&records, &detail::RecordOpsFor<Record>, TableInfo{Version, TableName, Schema});
189 }
190
191 TableCore _core;
192 };
193}
The owning byte buffer file contents are read into.
The erased engine of one table: identity + records access + preserved decode state,...
void wire(void *recordsVec, const detail::RecordOps *ops, TableInfo info)
Point the core at its owner's records vector and identity.
A client database table: the typed records of one DBFilesClient file.
Definition table.hpp:51
const TableCore & core() const
The erased engine (bindings and tests reach the shared machinery here).
Definition table.hpp:166
Result< FileBuffer > write(EncryptedPolicy policy=EncryptedPolicy::Preserve) const
Serialize the table.
Definition table.hpp:112
Result< void > write(fs::FileSystem &fs, const FileKey &key, EncryptedPolicy policy=EncryptedPolicy::Preserve) const
Serialize the table into a client filesystem (project overlay).
Definition table.hpp:123
Result< void > read(fs::FileSystem &fs, const FileKey &key)
Load the table from a client filesystem.
Definition table.hpp:98
std::vector< Record > records
The decoded records, file order.
Definition table.hpp:60
Result< void > read(std::span< const std::byte > data)
Decode a table image.
Definition table.hpp:90
static constexpr ClientVersion Version
The client version the record schema belongs to.
Definition table.hpp:54
formats::ValidationReport validate() const
Definition table.hpp:156
Result< void > ensureValid() const
Validate and raise on the first error instead of returning a report — the assert-style face of valida...
Definition table.hpp:163
const formats::StringBlock & strings() const
The preserved string block the record string fields were decoded from.
Definition table.hpp:134
Table & operator=(const Table &o)
Definition table.hpp:69
static constexpr std::string_view TableName
The WoWDBDefs table name (e.g.
Definition table.hpp:57
bool fullyDecoded() const
Whether every record of the file was decoded (no encrypted sections).
Definition table.hpp:147
Table(const Table &o)
Definition table.hpp:63
const std::vector< EncryptedSection > & encryptedSections() const
The encrypted sections skipped on the last read (empty when the file was fully decodable or is not a ...
Definition table.hpp:140
Table(Table &&o) noexcept
Definition table.hpp:65
Table & operator=(Table &&o) noexcept
Definition table.hpp:76
Client version identity, the flavor axis that separates a client's CONTENT version from the engine ge...
The type-erased boundary between the templated Table<Record> facade (table.hpp) and the per-format co...
The error-handling vocabulary: ErrorCode, Error and the Result<T> alias every fallible wowlib operati...
File identity types: the strong FileDataID and the FileKey a read request travels as.
The runtime facade over the static compositions — the primary welder binding surface of the fs layer.
constexpr RecordOps RecordOpsFor
The RecordOps instance of Record — the entire per-record residue.
EncryptedPolicy
How write() treats a table that still holds keyless (undecryptable) encrypted sections.
Definition codec.hpp:33
@ Preserve
Re-emit the original image verbatim; edits are not applied.
Definition codec.hpp:34
consteval auto schemaOf()
The column schema of record Record, derived by reflection: one Column per member, declaration order,...
Definition schema.hpp:220
std::expected< T, Error > Result
Every fallible wowlib operation returns Result<T>; bindings translate the error branch into a target-...
Definition error.hpp:100
The record bridge: ErasedRecordSink / ErasedRecordSource implement the non-templated RecordSink / Rec...
Schema reflection over generated client-database record structs: the column list, record stride and f...
StringBlock — the decoded representation of a chunk of zero-terminated strings (MOTX,...
The per-table identity a codec needs beyond the record data: the client version (format selection,...
Definition codec.hpp:58
TableCore + TableBase — the non-templated heart of every client-database table, and the ONE welded su...
The validation vocabulary: the severity scale, the single finding and the report validate() fills.