56#if !defined(WOWLIB_DB_SCHEMA_EMBEDDED) || !WOWLIB_DB_SCHEMA_EMBEDDED
57#error "wowlib/db/typed.hpp needs the embedded schema blob \
58(WOWLIB_DB_SCHEMA=embedded|both): the consteval validation reads it"
67#embed <wowlib_schema.wdbs>
82 if (!at)
throw TypedMismatch{
"the schema blob knows no table of this name"};
83 std::size_t era = SIZE_MAX;
84 for (std::size_t i = 0; i < view.
eraCount(); ++i)
87 throw TypedMismatch{
"no targeted era shares the struct's major version"};
89 for (std::size_t r = 0; r < entry.
rangeCount; ++r) {
91 if (range.
eraMask & (std::uint16_t{1} << era))
return range;
93 throw TypedMismatch{
"the table has no schema range covering the struct's era"};
101 for (std::size_t c = 0; c < range.
columnCount; ++c)
103 throw TypedMismatch{
"the era's schema has no column with this member's name"};
108 template <
typename Record>
113 const std::size_t at =
typedColumnIndex(Record::TableName, Record::Version, member.nameView());
115 if (col.
type != member.type)
117 "the member's value class (Int/Float/String/" "LocString) differs from the DBD column's"
120 throw TypedMismatch{
"the member's integer width or signedness " "differs from the DBD column's"};
121 if (col.
arrayLen != member.arrayLen)
122 throw TypedMismatch{
"the member's array length differs from the DBD column's"};
124 throw TypedMismatch{
"the member's LocString locale count differs " "from the DBD column's (wrong era?)"};
131 template <
typename Record>
133 std::vector<std::size_t> map;
135 map.push_back(
typedColumnIndex(Record::TableName, Record::Version, member.nameView()));
136 return std::define_static_array(map);
140 template <std::
size_t N>
144 consteval std::string_view
view()
const {
return {
text, N - 1}; }
154 template <TableRecord Record>
162 return DynTable::open(Record::TableName, Record::Version).transform([](
DynTable&&
table) {
164 out._table = std::move(
table);
177 return _table.read(data);
182 return _table.write(policy);
188 std::vector<Record>
load()
const {
189 std::vector < Record > out(_table.rowCount());
193 for (std::size_t r = 0; r < out.size(); ++r)
194 for (std::size_t m = 0; m < Schema.size(); ++m) _copyCellIn(sink, r, m, Projection[m], Schema[m]);
207 for (std::size_t r = 0; r < records.size(); ++r) {
209 for (std::size_t m = 0; m < Schema.size(); ++m) _copyCellOut(source, r, m, Projection[m], Schema[m]);
218 template <detail::FixedString Name>
221 constexpr std::size_t index = []()
consteval {
222 for (std::size_t i = 0; i < Members.size(); ++i)
223 if (std::meta::identifier_of(Members[i]) == Name.view())
return i;
226 using F = [:std::meta::type_of(Members[index]):];
227 static_assert(std::is_arithmetic_v<F> && !std::is_same_v<F, bool>,
228 "column<\"name\">() serves scalar arithmetic columns; "
229 "load() or the generic accessors cover the rest");
231 const auto view = _table.podColumn(Projection[index]);
234 using CF = std::add_const_t<F>;
235 CF* data =
reinterpret_cast<CF*
>(view->bytes.data());
236 const std::size_t count = view->bytes.size() /
sizeof(F);
237 return std::span<CF>(data, count);
250 const Column& shape)
const {
251 switch (shape.
type) {
253 for (std::size_t e = 0; e < shape.
arrayLen; ++e) sink.
setInt(r, m, e, _table.
getInt(r, col, e).value());
259 for (std::size_t e = 0; e < shape.
arrayLen; ++e) sink.
260 setString(r, m, e, _table.
getString(r, col, e).value());
264 r, m, e, _table.
getString(r, col, e).value());
271 void _copyCellOut(
const ErasedRecordSource& source,
275 const Column& shape) {
276 switch (shape.type) {
278 for (std::size_t e = 0; e < shape.arrayLen; ++e) _table.
setInt(r, col, source.getInt(r, m, e), e).value();
281 for (std::size_t e = 0; e < shape.arrayLen; ++e)
282 _table.
setFloat(r, col, std::bit_cast<float>(source.getSlot(r, m, e)), e).value();
285 for (std::size_t e = 0; e < shape.arrayLen; ++e) _table.
setString(r, col, source.getString(r, m, e), e).
289 for (std::size_t e = 0; e < shape.localeCount; ++e) _table.
setString(r, col, source.getString(r, m, e), e).
291 _table.
setLocstringFlags(r, col,
static_cast<std::uint32_t
>(source.getInt(r, m, 0))).value();
The generic client-database table: schema resolved at runtime from the schema catalog,...
Result< void > setString(std::size_t row, std::size_t column, std::string_view value, std::size_t element=0)
Write a string element.
Result< std::string_view > getString(std::size_t row, std::size_t column, std::size_t element=0) const
Read a string element (String columns: the array element; LocString columns: the locale slot).
Result< void > setFloat(std::size_t row, std::size_t column, float value, std::size_t element=0)
Write a float element.
Result< std::int64_t > getInt(std::size_t row, std::size_t column, std::size_t element=0) const
Read an integer element.
Result< std::uint32_t > locstringFlags(std::size_t row, std::size_t column) const
Read a LocString column's flags word.
Result< void > setLocstringFlags(std::size_t row, std::size_t column, std::uint32_t flags)
Write a LocString column's flags word.
Result< void > setInt(std::size_t row, std::size_t column, std::int64_t value, std::size_t element=0)
Write an integer element (truncates to the column's exact width, as the typed member assignment did).
Result< float > getFloat(std::size_t row, std::size_t column, std::size_t element=0) const
Read a float element.
RecordSink over a live std::vector<Record>& — the decode target.
void setInt(std::size_t record, std::size_t column, std::size_t element, std::int64_t value) override
void setFloat(std::size_t record, std::size_t column, std::size_t element, float value) override
void setString(std::size_t record, std::size_t column, std::size_t element, std::string_view value) override
RecordSource over a const std::vector<Record>& — the encode source.
A typed, consteval-validated face over one DynTable: the table itself stays fully generic (every colu...
Result< void > read(std::span< const std::byte > data)
Decode a table file image (sugar for table().read).
std::vector< Record > load() const
Materialize every row as a Record — the projection copies only the declared columns,...
const DynTable & table() const
The generic table under this face — decode/encode/validation and the generic cell accessors all live ...
Result< FileBuffer > write(EncryptedPolicy policy=EncryptedPolicy::Preserve) const
Serialize (sugar for table().write).
auto column() const
The zero-copy typed span of scalar column Name (rows x 1; array and string columns read through load ...
DynTable & table()
The generic table under this face — decode/encode/validation and the generic cell accessors all live ...
void writeBack(const std::vector< Record > &records)
Replace the table's rows from records.
static Result< TypedTable > open()
Open the era-resolved generic table with an empty row set.
A structural view over one WDBS blob.
constexpr ColumnEntry column(std::size_t i) const
The column entry i (blob-global index).
constexpr TableEntry table(std::size_t i) const
The directory entry of table i (name-sorted order).
constexpr std::optional< std::size_t > findTable(std::string_view name) const
Binary-search the (name-sorted) table directory for name.
constexpr std::size_t eraCount() const
constexpr ClientVersion era(std::size_t i) const
The client version of era slot i.
constexpr RangeEntry range(std::size_t i) const
The range entry i (blob-global index).
constexpr std::string copyStringAt(std::uint32_t off) const
The pool string at off, copied byte by byte — the consteval-safe twin of stringAt.
DynTable — the generic, runtime-schema client-database table: the ONE table class every binding welds...
The error-handling vocabulary: ErrorCode, Error and the Result<T> alias every fallible wowlib operati...
consteval std::size_t typedColumnIndex(std::string_view table, ClientVersion version, std::string_view name)
The era-schema column index whose name is name, or a thrown TypedMismatch.
consteval auto recordMembers()
The reflected non-static data members of record Record, declaration order.
consteval bool typedValidate()
Validate Record against the blob (see the file note for the rules); also the projection builder's pre...
consteval blob::RangeEntry typedRangeOf(std::string_view table, ClientVersion version)
The blob's column list for (table, version)'s era, as blob-global column indexes [first,...
consteval auto typedProjection()
The projection map of Record: member position -> era-schema column index, as a static (never-dangling...
constexpr unsigned char TypedSchemaBlob[]
The blob, again, for CONSTANT EVALUATION in consumer TUs (the runtime catalog's copy lives inside sch...
@ Int
An integer column; Column::bits / Column::isSigned give the shape.
@ Float
A 32-bit IEEE float column.
@ String
A string-block reference column (u32 offset on disk).
@ LocString
A pre-Cataclysm localized string column (see LocString).
EncryptedPolicy
How write() treats a table that still holds keyless (undecryptable) encrypted sections.
@ Preserve
Re-emit the original image verbatim; edits are not applied.
consteval auto schemaOf()
The column schema of record Record, derived by reflection: one Column per member, declaration order,...
std::expected< T, Error > Result
Every fallible wowlib operation returns Result<T>; bindings translate the error branch into a target-...
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...
The WDBS schema-blob format: a constexpr-parseable view over the compact binary dbdgen emits (--schem...
std::uint16_t major
Expansion number, e.g.
One column of a record schema, derived from a record member by reflection (typed records) or from the...
std::uint8_t localeCount
LocString language slots (8 or 16); 0 otherwise.
std::uint16_t arrayLen
Element count; 1 for scalar columns.
ColumnType type
The logical value class.
One column, decoded to the raw blob facts (the catalog turns this into a wowlib::db::Column with an i...
std::uint16_t arrayLen
element count; 1 for scalars.
std::uint32_t nameOff
The column name's pool offset.
std::uint8_t localeCount
LocString language slots; 0 otherwise.
ColumnType type
The logical value class.
std::uint8_t bits
Integer element width in bits.
One schema range: a run of columns valid for the eras in the mask.
std::uint32_t firstColumn
Index of the range's first column.
std::uint16_t eraMask
Bit i set = valid for the blob's era i.
std::uint16_t columnCount
Number of consecutive columns.
One table's directory entry, decoded.
std::uint32_t rangeCount
Number of consecutive ranges.
std::uint32_t firstRange
Index of the table's first range.
consteval std::string_view view() const
consteval FixedString(const char(&s)[N])
The consteval-validation failure carrier: throwing it inside constant evaluation aborts compilation w...