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
|
#ifndef TESDATA_FORMPARSER_H
#define TESDATA_FORMPARSER_H
#include "DataItem.h"
#include "TESFile/Stream.h"
#include "TESFile/Type.h"
#include <coroutine>
#include <istream>
#include <map>
#include <memory>
#include <span>
#include <string>
using namespace Qt::Literals::StringLiterals;
namespace TESData
{
namespace Parse
{
struct Promise;
struct Task : std::coroutine_handle<Promise>
{
using promise_type = Promise;
Task(std::coroutine_handle<Promise>&& promise)
: std::coroutine_handle<Promise>::coroutine_handle(promise)
{}
};
struct Promise
{
Task get_return_object() { return {Task::from_promise(*this)}; }
std::suspend_always initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
} // namespace Parse
using ParseTask = Parse::Task;
class IFormParser
{
public:
virtual void parseFlags(DataItem* root, int fileIndex, std::uint32_t flags) const = 0;
virtual ParseTask parseForm(DataItem* root, int fileIndex, bool localized,
std::span<const std::string> masters,
const std::string& plugin, const TESFile::Type& signature,
std::istream* const& stream) const = 0;
};
class FormParserManager final
{
template <typename T, TESFile::Type Type>
friend struct RegisterFormParser;
public:
enum class Game
{
TES4,
FO3,
FNV,
TES5,
FO4,
SSE,
Unknown
};
FormParserManager() = delete;
[[nodiscard]] static std::shared_ptr<const IFormParser> getParser(Game game,
TESFile::Type type);
private:
using RegistrationMap = std::map<TESFile::Type, std::shared_ptr<IFormParser>>;
static auto registrationMap() -> RegistrationMap&;
};
template <typename T, TESFile::Type Type>
struct [[maybe_unused]] RegisterFormParser
{
explicit RegisterFormParser()
{
FormParserManager::registrationMap().emplace(Type, std::make_shared<T>());
}
};
template <TESFile::Type Type = {}>
class FormParser : public IFormParser
{
inline static RegisterFormParser<FormParser<Type>, Type> reg{};
public:
void parseFlags(DataItem* root, int fileIndex, std::uint32_t flags) const override;
ParseTask parseForm(DataItem* root, int fileIndex, bool localized,
std::span<const std::string> masters, const std::string& plugin,
const TESFile::Type& signature,
std::istream* const& stream) const override;
};
QString readBytes(std::istream& stream, int size);
QString readLstring(bool localized, std::istream& stream);
QString readFormId(std::span<const std::string> masters, const std::string& plugin,
std::istream& stream);
} // namespace TESData
#endif // TESDATA_FORMPARSER_H
|