12 u
" message not available. "
13 u
"(1:^1, 2:^2, 3:^3, A:^A, P:^P, S:^S)";
17 const std::byte*
bytes)
noexcept
20 static_cast<std::uint16_t
>(
21 std::to_integer<std::uint8_t>(
bytes[0])) |
22 static_cast<std::uint16_t
>(
23 std::to_integer<std::uint8_t>(
bytes[1]) << 8U);
30 std::optional<DataTag> tag = std::nullopt)
32 return { code, {}, tag, std::move(detail) };
39 const auto result = std::to_chars(
53 std::span<const std::byte>
bytes)
59 "legacy UTF-16LE payload must have a non-zero even size"));
77 "non-zero data follows the UTF-16 terminator"));
95 "high surrogate is not followed by a code unit"));
98 const char16_t low =
static_cast<char16_t>(
105 "high surrogate is not followed by a low surrogate"));
118 "unpaired low surrogate in UTF-16 payload"));
128 "legacy string payload has no UTF-16 NUL terminator"));
135 std::expected<std::shared_ptr<LanguageCatalog>, DataError>
138 std::shared_ptr<LegacyDataArchive> textArchive)
144 "language ID must be in the source-defined range 1..10"));
147 if (!textArchive || !textArchive->isOpen())
151 "language text archive is absent or closed"));
154 if (textArchive->group() !=
159 "language text archive must use DAT_LANG group 9"));
173 "language item tag 0 must be an index table",
177 auto indexBytes = textArchive->load(0);
181 return std::unexpected(indexBytes.error());
195 auto target = textArchive->metadata(
entry.dataTag);
201 "language index references a tag outside the DAT bank";
202 return std::unexpected(std::move(
error));
209 "language index target must be a DataString item",
214 auto catalog = std::shared_ptr<LanguageCatalog>(
217 catalog->legacyArchive_ = std::move(textArchive);
218 catalog->maximumMessageId_ =
225 std::expected<std::shared_ptr<LanguageCatalog>,
DataError>
228 std::shared_ptr<const DataSource>
source)
234 "language ID must be in the source-defined range 1..10"));
241 "language DATA source is absent"));
244 const auto languageId = [](
DataTag tag)
257 "language item tag 0 must be an index table",
261 auto indexBytes =
source->load(languageId(0));
263 return std::unexpected(indexBytes.error());
276 "language index references a tag outside the DATA source";
277 return std::unexpected(std::move(
error));
284 "language index target must be a DataString item",
289 auto catalog = std::shared_ptr<LanguageCatalog>(
292 catalog->source_ = std::move(
source);
293 catalog->maximumMessageId_ =
308 return maximumMessageId_;
312 std::expected<std::optional<SharedLanguageText>,
DataError>
315 std::scoped_lock lock(mutex_);
317 if (
const auto cached = cache_.find(
messageId);
318 cached != cache_.end())
320 return std::optional<SharedLanguageText>{ cached->second };
327 return std::optional<SharedLanguageText>{};
330 std::expected<SharedDataBytes, DataError>
bytes =
334 : legacyArchive_->load(*tag);
338 return std::unexpected(
bytes.error());
347 error.path = legacyArchive_->path();
349 return std::unexpected(std::move(
error));
352 auto text = std::make_shared<const std::u16string>(
355 return std::optional<SharedLanguageText>{ std::move(
text) };
359 std::expected<SharedLanguageText, DataError>
366 return std::unexpected(
direct.error());
401 return std::make_shared<const std::u16string>(std::move(
fallback));
405 std::expected<SharedLanguageText, DataError>
412 return std::unexpected(
source.error());
432 return std::const_pointer_cast<const std::u16string>(
cleaned);
443 if (definitions ==
nullptr)
447 "language ID must be in the source-defined range 1..10"));
451 for (
const auto* definition :
452 { &definitions->text, &definitions->graphics, &definitions->dialog })
455 legacyRoot / std::filesystem::path(definition->legacyPath),
459 return std::unexpected(
mounted.error());
471 if (definitions ==
nullptr)
475 "language ID must be in the source-defined range 1..10"));
483 return std::unexpected(
text.error());
491 return std::unexpected(
media.error());
499 return std::unexpected(dialog.error());
502 if (!(*media)->isOpen() || !(*dialog)->isOpen())
506 "language media or dialog archive is closed"));
513 auto error = catalog.error();
514 error.path = (*text)->path();
515 return std::unexpected(std::move(
error));
527 std::scoped_lock lock(mutex_);
528 active_ = std::move(
staged);
535 std::shared_ptr<const DataSource>
source,
539 if (definitions ==
nullptr)
543 "language ID must be in the source-defined range 1..10"));
550 "language DATA source is absent"));
556 return std::unexpected(
text.error());
561 return std::unexpected(
media.error());
566 return std::unexpected(dialog.error());
568 if (!(*text)->isOpen() ||
569 !(*media)->isOpen() ||
570 !(*dialog)->isOpen())
574 "language archive compatibility owners are closed"));
582 auto error = catalog.error();
583 if (
error.path.empty())
584 error.path = (*text)->path();
585 return std::unexpected(std::move(
error));
597 std::scoped_lock lock(mutex_);
598 active_ = std::move(
staged);
603 std::shared_ptr<const LanguageSnapshot>
606 std::scoped_lock lock(mutex_);
613 std::scoped_lock lock(mutex_);
std::vector< std::byte > bytes
std::shared_ptr< const data::HmdTextureImage > source
std::deque< Bytes > output
std::expected< std::shared_ptr< LegacyDataArchive >, DataError > mount(const std::filesystem::path &path, std::uint16_t group, ArchiveOpenOptions options={})
std::optional< DataTag > find(std::uint32_t indexValue) const noexcept
static std::expected< DataIndexTable, DataError > parse(std::span< const std::byte > bytes)
LanguageId language() const noexcept
std::uint32_t maximumMessageId() const noexcept
static std::expected< std::shared_ptr< LanguageCatalog >, DataError > open(LanguageId language, std::shared_ptr< LegacyDataArchive > textArchive)
std::expected< SharedLanguageText, DataError > cleanMessage(std::uint32_t messageId) const
std::expected< SharedLanguageText, DataError > message(std::uint32_t messageId) const
std::expected< std::optional< SharedLanguageText >, DataError > lookup(std::uint32_t messageId) const
std::shared_ptr< const LanguageSnapshot > snapshot() const noexcept
std::expected< void, DataError > select(const std::filesystem::path &legacyRoot, LanguageId language, ArchiveOpenOptions options={})
constexpr std::uint16_t legacyGroupValue(LegacyGroupId group) noexcept
std::expected< std::u16string, DataError > decodeLegacyUtf16Le(std::span< const std::byte > bytes)
const LanguageBankTriplet * findLanguageBankTriplet(LanguageId language) noexcept
constexpr DataId packDataId(std::uint16_t group, DataTag tag) noexcept