Repository navigation
Expand file tree
/
Copy pathtre_library.cpp
More file actions
207 lines (175 loc) · 5.41 KB
/
Copy pathtre_library.cpp
File metadata and controls
207 lines (175 loc) · 5.41 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include "stdafx.h"
#include "tre_library.h"
#include <filesystem>
namespace Tre_navigator
{
namespace fs = std::filesystem;
namespace test = std::experimental::filesystem;
using namespace std;
Tre_library::Tre_library(const string& path, Tre_library_reader_callback* callback_ptr)
{
// Validate the path first
if (path.empty())
{
throw std::runtime_error("TRE library path cannot be empty");
}
if (!fs::exists(path))
{
throw std::runtime_error("TRE library path does not exist: " + path);
}
if (!fs::is_directory(path))
{
throw std::runtime_error("TRE library path is not a directory: " + path);
}
try
{
fs::directory_iterator file_enum(path);
vector<string> files;
for (auto& file_item : file_enum)
{
if (fs::is_regular_file(file_item) && file_item.path().extension() == ".tre")
files.push_back(file_item.path().string());
}
sort(files.begin(), files.end());
if (callback_ptr != nullptr)
callback_ptr->number_of_files(files.size());
// Track failed files for reporting
vector<string> failed_files;
size_t successfully_loaded = 0;
for (auto& filename : files)
{
try
{
std::cout << "Loading TRE file: " << fs::path(filename).filename().string() << std::flush;
if (filename == "C:\\SWG\\patch_18_client_00.tre")
{
std::cout << " (known problematic file)" << std::flush;
}
auto reader = std::make_shared<Tre_reader>(filename);
m_readers.push_back(reader);
auto resources_num = reader->get_resource_count();
for (uint32_t idx = 0; idx < resources_num; ++idx)
{
auto res_name = reader->get_resource_name(idx);
m_reader_lookup.insert(std::make_pair(res_name, reader));
}
std::cout << " - OK (" << resources_num << " resources)" << std::endl;
successfully_loaded++;
if (callback_ptr != nullptr)
callback_ptr->file_read();
}
catch (const std::exception& e)
{
// Log the failed file but continue processing others
std::cout << " - FAILED" << std::endl;
std::cerr << "Error details: " << e.what() << std::endl;
failed_files.push_back(filename);
if (callback_ptr != nullptr)
callback_ptr->file_read(); // Still report progress
}
}
// Report summary
std::cout << "TRE Library loaded: " << successfully_loaded << " files successfully";
if (!failed_files.empty())
{
std::cout << ", " << failed_files.size() << " files failed to load";
}
std::cout << std::endl;
// If no files were loaded successfully, that's a fatal error
if (successfully_loaded == 0)
{
std::string error_msg = "No TRE files could be loaded from: " + path;
if (!failed_files.empty())
{
error_msg += "\nFailed files:";
for (const auto& failed_file : failed_files)
{
error_msg += "\n - " + failed_file;
}
}
throw std::runtime_error(error_msg);
}
}
catch (const fs::filesystem_error& e)
{
throw std::runtime_error("Filesystem error while accessing TRE library path '" + path + "': " + e.what());
}
catch (const std::exception& e)
{
throw std::runtime_error("Failed to initialize TRE library from path '" + path + "': " + e.what());
}
}
bool Tre_library::is_object_present(const std::string& name)
{
auto result = m_reader_lookup.find(name);
return result != m_reader_lookup.end();
}
bool Tre_library::get_object_name(const std::string& partial_name, std::string& full_name)
{
regex pattern("(.*)" + partial_name);
auto result = find_if(m_reader_lookup.begin(), m_reader_lookup.end(),
[&pattern](const pair<string, weak_ptr<Tre_reader>>& item)
{
return regex_match(item.first, pattern);
});
auto ret = result != m_reader_lookup.end();
if (ret)
full_name = result->first;
return ret;
}
size_t Tre_library::number_of_object_versions(const string& name)
{
auto object = m_reader_lookup.find(name);
if (object != m_reader_lookup.end())
{
auto readers_range = m_reader_lookup.equal_range(name);
return std::distance(readers_range.first, readers_range.second);
}
return size_t(-1);
}
vector<weak_ptr<Tre_reader>> Tre_library::get_versioned_readers(const string& name)
{
vector<weak_ptr<Tre_reader>> result;
auto object = m_reader_lookup.find(name);
if (object != m_reader_lookup.end())
{
auto range = m_reader_lookup.equal_range(name);
for (auto it = range.first; it != range.second; ++it)
result.push_back(it->second);
}
return result;
}
bool Tre_library::get_object(const string& name, vector<uint8_t>& buffer, size_t version_num, bool search)
{
string fullname;
if (!is_object_present(name))
{
if (!search || !get_object_name(name, fullname))
return false;
}
else
fullname = name;
auto readers = get_versioned_readers(fullname);
if (version_num > readers.size())
return false;
auto reader_lock = readers[version_num].lock();
if (reader_lock)
return reader_lock->get_resource(fullname, buffer);
return false;
}
bool Tre_library::select_objects_by_ext(const string& ext, vector<string>& result)
{
if (ext.length() != 3)
return false;
for (auto& object : m_reader_lookup)
{
auto object_name = object.first;
auto obj_ext = object_name.substr(object_name.length() - 3);
if (obj_ext == ext)
result.push_back(object_name);
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result.empty() == false;
}
}