blob: 2351c0593eecb89d32327324257d84297b06b422 (
plain) (
blame)
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
116
117
118
119
120
121
122
123
124
|
#include <rez.h>
#include <rez/dir.h>
#include <rez/io.h>
#include <cctype>
#include <iostream>
#include <memory>
#include <sstream>
#include <variant>
std::string rez::ball::toupper(const std::string &s) const
{
std::string ret;
// Assume ASCII encoding.
for (const auto &c: s)
ret += std::toupper(c);
return ret;
}
std::unique_ptr<rez::file> rez::ball::open(const char *path)
{
std::istringstream stream(path);
std::string token;
const rez::dir *dir = &root_dir;
const rez::resource *resource = nullptr;
while (std::getline(stream, token, '/'))
{
std::string uctoken = toupper(token);
const auto &map = dir->entries();
auto it = map.find(uctoken);
if (it == map.end())
return nullptr;
const rez::dir::direntry &de = it->second;
if (std::holds_alternative<rez::dir>(de))
dir = &std::get<rez::dir>(de);
else if (std::holds_alternative<rez::resource>(de))
{
dir = nullptr;
resource = &std::get<rez::resource>(de);
}
}
if (dir)
{
std::cerr << path << " is a directory\n";
return nullptr;
}
else if (!resource)
{
std::cerr << io.path() << ": could not find " << path << '\n';
return nullptr;
}
return std::make_unique<rez::file>(*resource, io);
}
int rez::ball::parse()
{
static const char title[63] =
"\r\nRezMgr Version 1 Copyright (C) 1995 MONOLITH INC. ",
subtitle[65] =
"\r\nLithTech Resource File \r\n";
if (io.open())
return -1;
else if (io.check(title))
{
std::cerr << path << ": wrong title\n";
return -1;
}
else if (io.check(subtitle))
{
std::cerr << path << ": wrong subtitle\n";
return -1;
}
else if (io.check(0x1a))
{
std::cerr << path << ": wrong EOF\n";
return -1;
}
struct
{
uint32_t w[N_WORDS];
uint8_t is_sorted;
} header;
for (auto &w : header.w)
if (io.read_le(w))
return -1;
if (header.w[FILE_FORMAT_VERSION] != 1)
{
std::cerr << path << ": expected file format version 1, got "
<< header.w[FILE_FORMAT_VERSION] << '\n';
return -1;
}
else if (io.read(header.is_sorted))
{
std::cerr << path << ": could not read sorted flag" << '\n';
return -1;
}
struct rez::entry::cfg cfg = {0};
cfg.size = header.w[ROOT_DIR_SIZE];
cfg.offset = header.w[ROOT_DIR_POS];
cfg.maxcomlen = header.w[MAX_COMMENT_SIZE];
cfg.maxdirlen = header.w[MAX_DIR_NAME_SIZE];
cfg.maxreslen = header.w[MAX_REZ_NAME_SIZE];
root_dir.read(cfg, io, 0);
return 0;
}
rez::ball::ball(const char *path) :
path(path),
io(path)
{
}
|