wowlib
0.0.0
Read & write World of Warcraft client files — a C++26 core
Toggle main menu visibility
Loading...
Searching...
No Matches
string_block.hpp
Go to the documentation of this file.
1
#pragma once
2
7
8
#include <algorithm>
9
#include <cstddef>
10
#include <cstdint>
11
#include <cstring>
12
#include <span>
13
#include <string>
14
#include <string_view>
15
#include <vector>
16
17
#include <welder/vocabulary.hpp>
18
19
#include <
wowlib/core/buffer.hpp
>
20
#include <
wowlib/core/error.hpp
>
21
22
namespace
wowlib::formats
{
23
class
[[
24
=welder::weld,
25
=welder::doc(R
"(
26
A chunk of zero-terminated strings (texture and model filenames, group
27
names), decoded into (offset, value) entries. Other chunks reference
28
entries by their byte offset in the on-disk blob; adding appends, and
29
existing offsets never move.)")
30
]]
StringBlock
{
31
public
:
32
struct
[[=welder::doc(
33
"One decoded string and the blob byte offset other chunks "
34
"reference it by."
)]]
Entry
{
35
[[=welder::doc(
"Byte offset of the string in the on-disk blob."
)]]
36
std::uint32_t offset = 0;
37
38
[[=welder::doc(
"The string, without its terminator."
)]]
39
std::string value;
40
};
41
42
StringBlock
() =
default
;
43
49
[[=welder::mark::exclude]]
50
Result<void>
read
(std::span<const std::byte> payload) {
51
_entries.clear();
52
_blobSize =
static_cast<
std::uint32_t
>
(payload.size());
53
const
auto
* bytes =
reinterpret_cast<
const
char
*
>
(payload.data());
54
for
(std::size_t pos = 0; pos < payload.size();) {
55
if
(bytes[pos] ==
'\0'
) {
56
++pos;
57
continue
;
58
}
59
std::size_t end = pos;
60
while
(end < payload.size() && bytes[end] !=
'\0'
) ++end;
61
_entries.push_back({
static_cast<
std::uint32_t
>
(pos), std::string{bytes + pos, end - pos}});
62
pos = end + 1;
63
}
64
return
{};
65
}
66
70
72
[[=welder::mark::exclude]]
73
Result<void>
write(
FileBuffer
& out)
const
{
74
const
std::size_t base = out.size();
75
out.resize(base + _blobSize);
// value-initialized: zero fill
76
for
(
const
Entry
& entry : _entries)
77
std::memcpy(out.data() + base + entry.offset, entry.value.data(), entry.value.size());
78
return
{};
79
}
80
81
[[nodiscard]]
82
[[=welder::doc(
"The string at a byte offset another chunk stored; empty if "
83
"the offset lands on padding or out of range."
),
84
=welder::returns(
"the referenced string (a mid-entry offset yields the "
85
"suffix)"
)]]
86
std::string_view at(std::uint32_t offset [[=welder::doc(
"byte offset into the on-disk blob"
)]])
const
{
87
// entries are ordered by offset: find the last one starting at or before
88
const
auto
after = std::ranges::upper_bound(_entries, offset, {}, &Entry::offset);
89
if
(after == _entries.begin())
return
{};
90
const
Entry
& entry = *std::prev(after);
91
const
std::uint32_t delta = offset - entry.
offset
;
92
if
(delta >= entry.
value
.size())
return
{};
93
return
std::string_view{entry.
value
}.substr(delta);
94
}
95
96
[[=welder::doc(
"Append a string; existing offsets never move."
),
97
=welder::returns(
"the offset the new string starts at - the value to "
98
"store in referencing chunks"
)]]
99
std::uint32_t add(std::string_view
string
100
[[=welder::doc(
"the string to append (no embedded zero "
101
"bytes)"
)]]) {
102
const
std::uint32_t offset = _blobSize;
103
_entries.push_back({offset, std::string{
string
}});
104
_blobSize +=
static_cast<
std::uint32_t
>
(
string
.size()) + 1;
105
return
offset;
106
}
107
108
[[nodiscard]]
109
[[=welder::doc(
"The decoded entries, in blob order."
),
110
=welder::returns(
"the (offset, value) entries"
)]]
111
const
std::vector<Entry>&
entries
()
const
{
112
return
_entries;
113
}
114
115
[[nodiscard]]
116
[[=welder::getter, =welder::doc(
"Whether the on-disk blob holds any bytes."
)
117
]]
118
bool
empty
()
const
{
119
return
_blobSize == 0;
120
}
121
122
[[=welder::getter,
123
=welder::doc(
"The on-disk blob size in bytes, trailing padding included."
)
124
]]
125
std::size_t size()
const
{
126
return
_blobSize;
127
}
128
129
private
:
130
std::vector<Entry> _entries;
131
std::uint32_t _blobSize = 0;
132
};
133
}
buffer.hpp
The owning byte buffer file contents are read into.
wowlib::formats::StringBlock::size
std::size_t size() const
The on-disk blob size in bytes, trailing padding included.
Definition
string_block.hpp:114
wowlib::formats::StringBlock::empty
bool empty() const
Whether the on-disk blob holds any bytes.
Definition
string_block.hpp:109
wowlib::formats::StringBlock::add
std::uint32_t add(std::string_view string)
Append a string; existing offsets never move.
Definition
string_block.hpp:90
wowlib::formats::StringBlock::at
std::string_view at(std::uint32_t offset) const
The string at a byte offset another chunk stored; empty if the offset lands on padding or out of rang...
Definition
string_block.hpp:76
wowlib::formats::StringBlock::entries
const std::vector< Entry > & entries() const
The decoded entries, in blob order.
Definition
string_block.hpp:103
wowlib::formats::StringBlock::read
Result< void > read(std::span< const std::byte > payload)
Decode a chunk payload (the serializer's read hook): every run of non-zero bytes becomes an entry at ...
Definition
string_block.hpp:41
wowlib::formats::StringBlock::StringBlock
StringBlock()=default
wowlib::formats::StringBlock::write
Result< void > write(FileBuffer &out) const
Blobify (the serializer's write hook): append size() zero bytes to out, then lay each entry's charact...
Definition
string_block.hpp:63
error.hpp
The error-handling vocabulary: ErrorCode, Error and the Result<T> alias every fallible wowlib operati...
wowlib::formats
Definition
adt.hpp:68
wowlib::Result
std::expected< T, Error > Result
Every fallible wowlib operation returns Result<T>; bindings translate the error branch into a target-...
Definition
error.hpp:100
wowlib::FileBuffer
std::vector< std::byte > FileBuffer
Owning byte buffer for file contents read out of a client storage.
Definition
buffer.hpp:16
wowlib::formats::StringBlock::Entry
One decoded string and the blob byte offset other chunks reference it by.
Definition
string_block.hpp:26
wowlib::formats::StringBlock::Entry::offset
std::uint32_t offset
Byte offset of the string in the on-disk blob.
Definition
string_block.hpp:28
wowlib::formats::StringBlock::Entry::value
std::string value
The string, without its terminator.
Definition
string_block.hpp:31
src
wowlib
formats
common
string_block.hpp
Generated by
1.17.0