diff options
-rw-r--r-- | .clang-format | 2 | ||||
-rw-r--r-- | .gitignore | 11 | ||||
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | heading.cpp | 121 | ||||
-rw-r--r-- | heading.h | 41 | ||||
-rw-r--r-- | main.cpp | 98 | ||||
-rw-r--r-- | scene.cpp | 139 | ||||
-rw-r--r-- | scene.h | 34 | ||||
-rw-r--r-- | script.cpp | 106 | ||||
-rw-r--r-- | script.h | 36 |
10 files changed, 596 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8de7fe6 --- /dev/null +++ b/.clang-format | |||
@@ -0,0 +1,2 @@ | |||
1 | --- | ||
2 | BasedOnStyle: Google | ||
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f85f339 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,11 @@ | |||
1 | build | ||
2 | CMakeFiles | ||
3 | cmake_install.cmake | ||
4 | CMakeCache.txt | ||
5 | compile_commands.json | ||
6 | Makefile | ||
7 | [._]*.s[a-v][a-z] | ||
8 | [._]*.sw[a-p] | ||
9 | [._]s[a-rt-v][a-z] | ||
10 | [._]ss[a-gi-z] | ||
11 | [._]sw[a-p] | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b4f5e05 --- /dev/null +++ b/CMakeLists.txt | |||
@@ -0,0 +1,8 @@ | |||
1 | cmake_minimum_required (VERSION 3.9) | ||
2 | project (godot3_tscn_compactor) | ||
3 | |||
4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||
5 | |||
6 | add_executable(godot3_tscn_compactor main.cpp heading.cpp scene.cpp script.cpp) | ||
7 | set_property(TARGET godot3_tscn_compactor PROPERTY CXX_STANDARD 17) | ||
8 | set_property(TARGET godot3_tscn_compactor PROPERTY CXX_STANDARD_REQUIRED ON) | ||
diff --git a/heading.cpp b/heading.cpp new file mode 100644 index 0000000..ff4a1a6 --- /dev/null +++ b/heading.cpp | |||
@@ -0,0 +1,121 @@ | |||
1 | #include <stdlib.h> | ||
2 | |||
3 | #include <sstream> | ||
4 | #include <stdexcept> | ||
5 | #include <string> | ||
6 | #include <string_view> | ||
7 | |||
8 | #include "heading.h" | ||
9 | |||
10 | Heading::Heading(std::string_view line) { | ||
11 | std::string original_line(line); | ||
12 | |||
13 | if (line[0] != '[') { | ||
14 | std::ostringstream errormsg; | ||
15 | errormsg << "Heading must start with [." << std::endl | ||
16 | << "Bad heading: " << original_line; | ||
17 | throw std::invalid_argument(errormsg.str()); | ||
18 | } | ||
19 | |||
20 | line.remove_prefix(1); | ||
21 | int divider = line.find_first_of(" ]"); | ||
22 | if (divider == std::string_view::npos) { | ||
23 | std::ostringstream errormsg; | ||
24 | errormsg << "Malformatted heading: " << line << std::endl | ||
25 | << "Original line: " << original_line; | ||
26 | throw std::invalid_argument(errormsg.str()); | ||
27 | } | ||
28 | |||
29 | type_ = line.substr(0, divider); | ||
30 | line.remove_prefix(divider + 1); | ||
31 | |||
32 | while (!line.empty()) { | ||
33 | divider = line.find_first_of("="); | ||
34 | if (divider == std::string_view::npos) { | ||
35 | std::ostringstream errormsg; | ||
36 | errormsg << "Malformatted heading: " << line << std::endl | ||
37 | << "Original line: " << original_line; | ||
38 | throw std::invalid_argument(errormsg.str()); | ||
39 | } | ||
40 | |||
41 | std::string key(line.substr(0, divider)); | ||
42 | line.remove_prefix(divider + 1); | ||
43 | |||
44 | if (line[0] == '"') { | ||
45 | line.remove_prefix(1); | ||
46 | divider = line.find_first_of("\""); | ||
47 | |||
48 | if (divider == std::string_view::npos) { | ||
49 | std::ostringstream errormsg; | ||
50 | errormsg << "Malformatted heading: " << line << std::endl | ||
51 | << "Original line: " << original_line; | ||
52 | throw std::invalid_argument(errormsg.str()); | ||
53 | } | ||
54 | |||
55 | std::string strval(line.substr(0, divider)); | ||
56 | line.remove_prefix(divider + 2); | ||
57 | |||
58 | keyvals_[key] = strval; | ||
59 | } else if (line[0] == 'S' || line[0] == 'E') { | ||
60 | ResourceRef rrval; | ||
61 | rrval.internal = (line[0] == 'S'); | ||
62 | |||
63 | line.remove_prefix(13); // SubResource(# | ||
64 | divider = line.find_first_of(" "); | ||
65 | |||
66 | if (divider == std::string_view::npos) { | ||
67 | std::ostringstream errormsg; | ||
68 | errormsg << "Malformatted heading: " << line << std::endl | ||
69 | << "Original line: " << original_line; | ||
70 | throw std::invalid_argument(errormsg.str()); | ||
71 | } | ||
72 | |||
73 | rrval.id = std::atoi(line.substr(0, divider).data()); | ||
74 | line.remove_prefix(divider + 3); | ||
75 | |||
76 | keyvals_[key] = rrval; | ||
77 | } else { | ||
78 | divider = line.find_first_of(" ]"); | ||
79 | |||
80 | if (divider == std::string_view::npos) { | ||
81 | std::ostringstream errormsg; | ||
82 | errormsg << "Malformatted heading: " << line << std::endl | ||
83 | << "Original line: " << original_line; | ||
84 | throw std::invalid_argument(errormsg.str()); | ||
85 | } | ||
86 | |||
87 | int numval = std::atoi(line.substr(0, divider).data()); | ||
88 | line.remove_prefix(divider + 1); | ||
89 | |||
90 | keyvals_[key] = numval; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | std::string Heading::ToString() const { | ||
96 | std::ostringstream output; | ||
97 | output << "["; | ||
98 | output << type_; | ||
99 | |||
100 | for (const auto& [key, value] : keyvals_) { | ||
101 | output << " " << key << "="; | ||
102 | |||
103 | if (std::holds_alternative<int>(value)) { | ||
104 | output << std::get<int>(value); | ||
105 | } else if (std::holds_alternative<ResourceRef>(value)) { | ||
106 | const auto& rrval = std::get<ResourceRef>(value); | ||
107 | if (rrval.internal) { | ||
108 | output << "Sub"; | ||
109 | } else { | ||
110 | output << "Ext"; | ||
111 | } | ||
112 | output << "Resource( " << rrval.id << " )"; | ||
113 | } else { | ||
114 | output << "\"" << std::get<std::string>(value) << "\""; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | output << "]" << std::endl; | ||
119 | |||
120 | return output.str(); | ||
121 | } | ||
diff --git a/heading.h b/heading.h new file mode 100644 index 0000000..1b1781b --- /dev/null +++ b/heading.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef HEADING_H | ||
2 | #define HEADING_H | ||
3 | |||
4 | #include <map> | ||
5 | #include <string> | ||
6 | #include <string_view> | ||
7 | #include <variant> | ||
8 | |||
9 | struct ResourceRef { | ||
10 | bool internal = false; | ||
11 | int id; | ||
12 | }; | ||
13 | |||
14 | class Heading { | ||
15 | public: | ||
16 | using keyval_t = std::variant<std::string, int, ResourceRef>; | ||
17 | |||
18 | Heading() = default; | ||
19 | |||
20 | explicit Heading(std::string_view line); | ||
21 | |||
22 | const std::string& type() const { return type_; } | ||
23 | |||
24 | void set_type(std::string_view type) { type_ = std::string(type); } | ||
25 | |||
26 | const keyval_t& GetKeyval(std::string_view key) const { | ||
27 | return keyvals_.at(std::string(key)); | ||
28 | } | ||
29 | |||
30 | void SetKeyval(std::string_view key, const keyval_t& value) { | ||
31 | keyvals_[std::string(key)] = value; | ||
32 | } | ||
33 | |||
34 | std::string ToString() const; | ||
35 | |||
36 | private: | ||
37 | std::string type_; | ||
38 | std::map<std::string, keyval_t> keyvals_; | ||
39 | }; | ||
40 | |||
41 | #endif /* HEADING_H */ | ||
diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9da0c40 --- /dev/null +++ b/main.cpp | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <filesystem> | ||
2 | #include <fstream> | ||
3 | #include <iostream> | ||
4 | #include <list> | ||
5 | #include <utility> | ||
6 | |||
7 | #include "heading.h" | ||
8 | #include "scene.h" | ||
9 | #include "script.h" | ||
10 | |||
11 | struct EmbeddedScript { | ||
12 | Script script; | ||
13 | bool internal = false; // true if referred from within another script | ||
14 | int id = -1; // if internal is false, ExtResource id | ||
15 | std::string path; // if internal is true | ||
16 | }; | ||
17 | |||
18 | void show_usage() { | ||
19 | std::cout << "godot3_tscn_compactor [path to root tscn] [file prefix]" | ||
20 | << std::endl; | ||
21 | } | ||
22 | |||
23 | int main(int argc, char** argv) { | ||
24 | if (argc != 3) { | ||
25 | show_usage(); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | std::filesystem::path root_tscn_path(argv[1]); | ||
30 | std::string file_prefix(argv[2]); | ||
31 | |||
32 | Scene root_tscn(root_tscn_path); | ||
33 | |||
34 | std::vector<EmbeddedScript> sub_scripts; | ||
35 | |||
36 | for (const auto& [id, heading] : root_tscn.ext_resources()) { | ||
37 | std::string resource_filename = | ||
38 | std::get<std::string>(heading.GetKeyval("path")); | ||
39 | if (resource_filename.substr(0, file_prefix.size()) == file_prefix) { | ||
40 | std::filesystem::path relative_filename = | ||
41 | resource_filename.substr(file_prefix.size()); | ||
42 | std::filesystem::path resource_path = | ||
43 | root_tscn_path.parent_path() / relative_filename; | ||
44 | |||
45 | EmbeddedScript embedded_script; | ||
46 | embedded_script.script = Script(resource_path, file_prefix); | ||
47 | embedded_script.id = id; | ||
48 | |||
49 | sub_scripts.push_back(std::move(embedded_script)); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | std::list<EmbeddedScript> all_scripts; | ||
54 | std::vector<EmbeddedScript> scripts_to_check = sub_scripts; | ||
55 | while (!scripts_to_check.empty()) { | ||
56 | std::vector<EmbeddedScript> cur_scripts; | ||
57 | cur_scripts.swap(scripts_to_check); | ||
58 | |||
59 | for (const EmbeddedScript& embedded_script : cur_scripts) { | ||
60 | all_scripts.push_front(embedded_script); | ||
61 | |||
62 | for (const std::string& loaded_script_path : | ||
63 | embedded_script.script.loaded_scripts()) { | ||
64 | std::filesystem::path resource_path = | ||
65 | root_tscn_path.parent_path() / loaded_script_path; | ||
66 | |||
67 | EmbeddedScript embedded_script; | ||
68 | embedded_script.script = Script(resource_path, file_prefix); | ||
69 | embedded_script.internal = true; | ||
70 | embedded_script.path = loaded_script_path; | ||
71 | |||
72 | scripts_to_check.push_back(std::move(embedded_script)); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | std::map<std::string, int> new_sub_scripts; | ||
78 | for (EmbeddedScript embedded_script : all_scripts) { | ||
79 | embedded_script.script.ReplaceScriptReferences(new_sub_scripts); | ||
80 | int sub_resource_id = root_tscn.AddSubResource(embedded_script.script); | ||
81 | |||
82 | if (embedded_script.internal) { | ||
83 | new_sub_scripts[embedded_script.path] = sub_resource_id; | ||
84 | } else { | ||
85 | root_tscn.RemoveExtResource(embedded_script.id); | ||
86 | root_tscn.ReplaceScriptReferences(embedded_script.id, sub_resource_id); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | std::filesystem::path output_name = root_tscn_path; | ||
91 | output_name.replace_filename(std::string(output_name.stem()) + | ||
92 | "_compiled.tscn"); | ||
93 | |||
94 | std::ofstream output_stream(output_name); | ||
95 | output_stream << root_tscn.ToString(); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
diff --git a/scene.cpp b/scene.cpp new file mode 100644 index 0000000..6eae537 --- /dev/null +++ b/scene.cpp | |||
@@ -0,0 +1,139 @@ | |||
1 | #include <filesystem> | ||
2 | #include <fstream> | ||
3 | #include <iomanip> | ||
4 | #include <iostream> | ||
5 | #include <map> | ||
6 | #include <sstream> | ||
7 | #include <stdexcept> | ||
8 | #include <string_view> | ||
9 | #include <variant> | ||
10 | |||
11 | #include "heading.h" | ||
12 | #include "scene.h" | ||
13 | |||
14 | Scene::Scene(const std::filesystem::path& path) { | ||
15 | std::ifstream input(path.c_str()); | ||
16 | std::string line; | ||
17 | bool section_started = false; | ||
18 | Heading cur_heading; | ||
19 | std::ostringstream cur_value; | ||
20 | bool value_started = false; | ||
21 | auto handle_end_of_section = [&]() { | ||
22 | section_started = false; | ||
23 | value_started = false; | ||
24 | |||
25 | if (cur_heading.type() == "sub_resource") { | ||
26 | sub_resources_[std::get<int>(cur_heading.GetKeyval("id"))] = { | ||
27 | cur_heading, cur_value.str()}; | ||
28 | } else { | ||
29 | other_.emplace_back(cur_heading, cur_value.str()); | ||
30 | } | ||
31 | |||
32 | cur_value = {}; | ||
33 | }; | ||
34 | while (std::getline(input, line)) { | ||
35 | if (section_started && (line.empty() || line[0] == '[')) { | ||
36 | handle_end_of_section(); | ||
37 | } | ||
38 | if (!line.empty() && line[0] == '[') { | ||
39 | Heading heading(line); | ||
40 | if (heading.type() == "gd_scene") { | ||
41 | file_descriptor_ = heading; | ||
42 | } else if (heading.type() == "ext_resource") { | ||
43 | ext_resources_[std::get<int>(heading.GetKeyval("id"))] = heading; | ||
44 | } else { | ||
45 | cur_heading = heading; | ||
46 | section_started = true; | ||
47 | } | ||
48 | } else if (!line.empty()) { | ||
49 | if (value_started) { | ||
50 | cur_value << std::endl; | ||
51 | } else { | ||
52 | value_started = true; | ||
53 | } | ||
54 | cur_value << line; | ||
55 | } | ||
56 | } | ||
57 | if (section_started) { | ||
58 | handle_end_of_section(); | ||
59 | } | ||
60 | |||
61 | for (const auto& [id, stuff] : sub_resources_) { | ||
62 | if (id >= next_sub_id_) { | ||
63 | next_sub_id_ = id + 1; | ||
64 | } | ||
65 | } | ||
66 | } | ||
67 | |||
68 | int Scene::AddSubResource(const Script& script) { | ||
69 | int new_id = next_sub_id_++; | ||
70 | |||
71 | std::ostringstream resource_contents; | ||
72 | for (const auto& [variable, value] : script.exports()) { | ||
73 | resource_contents << variable << " = SubResource( " << value << " )" | ||
74 | << std::endl; | ||
75 | } | ||
76 | resource_contents << "script/source = " << std::quoted(script.ToString()); | ||
77 | |||
78 | Heading heading; | ||
79 | heading.set_type("sub_resource"); | ||
80 | heading.SetKeyval("type", "GDScript"); | ||
81 | heading.SetKeyval("id", new_id); | ||
82 | |||
83 | sub_resources_[new_id] = {heading, resource_contents.str()}; | ||
84 | |||
85 | return new_id; | ||
86 | } | ||
87 | |||
88 | void Scene::RemoveExtResource(int id) { ext_resources_.erase(id); } | ||
89 | |||
90 | void Scene::ReplaceScriptReferences(int ext_id, int sub_id) { | ||
91 | auto replace_refs = [&](std::string& text) { | ||
92 | std::ostringstream search_str; | ||
93 | search_str << "ExtResource( " << ext_id << " )"; | ||
94 | std::string search = search_str.str(); | ||
95 | |||
96 | std::ostringstream new_text; | ||
97 | std::string_view corpus = text; | ||
98 | int location; | ||
99 | while ((location = corpus.find(search)) != std::string_view::npos) { | ||
100 | new_text << corpus.substr(0, location) << "SubResource( " << sub_id | ||
101 | << " )"; | ||
102 | corpus.remove_prefix(location + search.size()); | ||
103 | } | ||
104 | new_text << corpus; | ||
105 | |||
106 | text = new_text.str(); | ||
107 | }; | ||
108 | |||
109 | for (auto& [id, stuff] : sub_resources_) { | ||
110 | auto& [heading, text] = stuff; | ||
111 | replace_refs(text); | ||
112 | } | ||
113 | |||
114 | for (auto& [heading, text] : other_) { | ||
115 | replace_refs(text); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | std::string Scene::ToString() const { | ||
120 | std::ostringstream output; | ||
121 | output << file_descriptor_.ToString() << std::endl; | ||
122 | |||
123 | for (const auto& [id, heading] : ext_resources_) { | ||
124 | output << heading.ToString(); | ||
125 | } | ||
126 | |||
127 | output << std::endl; | ||
128 | |||
129 | for (const auto& [id, resource] : sub_resources_) { | ||
130 | const auto& [heading, value] = resource; | ||
131 | output << heading.ToString() << value << std::endl << std::endl; | ||
132 | } | ||
133 | |||
134 | for (const auto& [heading, value] : other_) { | ||
135 | output << heading.ToString() << value << std::endl << std::endl; | ||
136 | } | ||
137 | |||
138 | return output.str(); | ||
139 | } | ||
diff --git a/scene.h b/scene.h new file mode 100644 index 0000000..0ee9450 --- /dev/null +++ b/scene.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef SCENE_H | ||
2 | #define SCENE_H | ||
3 | |||
4 | #include <filesystem> | ||
5 | #include <map> | ||
6 | #include <tuple> | ||
7 | #include <vector> | ||
8 | |||
9 | #include "heading.h" | ||
10 | #include "script.h" | ||
11 | |||
12 | class Scene { | ||
13 | public: | ||
14 | explicit Scene(const std::filesystem::path& path); | ||
15 | |||
16 | const std::map<int, Heading>& ext_resources() const { return ext_resources_; } | ||
17 | |||
18 | int AddSubResource(const Script& script); | ||
19 | |||
20 | void RemoveExtResource(int id); | ||
21 | |||
22 | void ReplaceScriptReferences(int ext_id, int sub_id); | ||
23 | |||
24 | std::string ToString() const; | ||
25 | |||
26 | private: | ||
27 | Heading file_descriptor_; | ||
28 | std::map<int, Heading> ext_resources_; | ||
29 | std::map<int, std::tuple<Heading, std::string>> sub_resources_; | ||
30 | std::vector<std::tuple<Heading, std::string>> other_; | ||
31 | int next_sub_id_ = 0; | ||
32 | }; | ||
33 | |||
34 | #endif /* SCENE_H */ | ||
diff --git a/script.cpp b/script.cpp new file mode 100644 index 0000000..509d4a7 --- /dev/null +++ b/script.cpp | |||
@@ -0,0 +1,106 @@ | |||
1 | #include <filesystem> | ||
2 | #include <fstream> | ||
3 | #include <map> | ||
4 | #include <sstream> | ||
5 | #include <stdexcept> | ||
6 | #include <string> | ||
7 | #include <string_view> | ||
8 | |||
9 | #include "script.h" | ||
10 | |||
11 | Script::Script(const std::filesystem::path& path, std::string_view file_prefix) | ||
12 | : file_prefix_(file_prefix) { | ||
13 | { | ||
14 | std::ifstream script_file(path); | ||
15 | std::string line; | ||
16 | std::ostringstream text_stream; | ||
17 | while (std::getline(script_file, line)) { | ||
18 | text_stream << line << std::endl; | ||
19 | } | ||
20 | text_ = text_stream.str(); | ||
21 | } | ||
22 | |||
23 | std::string search = std::string("load(\"") + std::string(file_prefix); | ||
24 | std::string_view corpus = text_; | ||
25 | int location; | ||
26 | while ((location = corpus.find(search)) != std::string_view::npos) { | ||
27 | corpus.remove_prefix(location + search.size()); | ||
28 | int divider = corpus.find_first_of("\""); | ||
29 | if (divider == std::string_view::npos) { | ||
30 | throw std::invalid_argument( | ||
31 | "I don't know how this is happening but I guess I gotta report it."); | ||
32 | } | ||
33 | std::string script_path(corpus.substr(0, divider)); | ||
34 | corpus.remove_prefix(divider + 1); | ||
35 | loaded_scripts_.push_back(script_path); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | void Script::ReplaceScriptReferences( | ||
40 | const std::map<std::string, int>& script_ids) { | ||
41 | std::ostringstream new_text; | ||
42 | std::string_view corpus = text_; | ||
43 | int divider = corpus.find_first_of("\n"); | ||
44 | if (divider == std::string_view::npos) { | ||
45 | throw std::invalid_argument("Script is one line??"); | ||
46 | } | ||
47 | new_text << corpus.substr(0, divider + 1) << std::endl; | ||
48 | ; | ||
49 | corpus.remove_prefix(divider + 1); | ||
50 | |||
51 | std::map<std::string, std::string> path_to_export; | ||
52 | for (const std::string& loaded_script : loaded_scripts_) { | ||
53 | std::ostringstream export_str; | ||
54 | export_str << "COMPACTED"; | ||
55 | |||
56 | std::filesystem::path name_path(loaded_script); | ||
57 | name_path.replace_filename(name_path.stem()); | ||
58 | for (const auto& segment : name_path) { | ||
59 | std::string segment_str(segment); | ||
60 | export_str << "_" << segment_str; | ||
61 | } | ||
62 | |||
63 | std::string export_name = export_str.str(); | ||
64 | exports_.emplace_back(export_name, script_ids.at(loaded_script)); | ||
65 | |||
66 | new_text << "export(Resource) var " << export_name << std::endl; | ||
67 | |||
68 | path_to_export[loaded_script] = export_name; | ||
69 | } | ||
70 | |||
71 | new_text << std::endl; | ||
72 | |||
73 | std::string search = std::string("load(\"") + file_prefix_; | ||
74 | std::string search_alt1 = std::string("preload(\"") + file_prefix_; | ||
75 | std::string search_alt2 = | ||
76 | std::string("ResourceLoader.load(\"") + file_prefix_; | ||
77 | int location; | ||
78 | while ((location = corpus.find(search)) != std::string_view::npos) { | ||
79 | int alt1 = corpus.find(search_alt1); | ||
80 | int alt2 = corpus.find(search_alt2); | ||
81 | int remove_size = search.size(); | ||
82 | |||
83 | if (alt1 != std::string_view::npos && alt1 < location) { | ||
84 | location = alt1; | ||
85 | remove_size = search_alt1.size(); | ||
86 | } else if (alt2 != std::string_view::npos && alt2 < location) { | ||
87 | location = alt2; | ||
88 | remove_size = search_alt2.size(); | ||
89 | } | ||
90 | |||
91 | new_text << corpus.substr(0, location); | ||
92 | corpus.remove_prefix(location + remove_size); | ||
93 | |||
94 | int divider = corpus.find_first_of("\""); | ||
95 | // TODO: ehhh error reporting | ||
96 | std::string referenced_path(corpus.substr(0, divider)); | ||
97 | corpus.remove_prefix(divider + 2); // the quote and the close paren | ||
98 | new_text << path_to_export.at(referenced_path); | ||
99 | } | ||
100 | |||
101 | new_text << corpus; | ||
102 | |||
103 | text_ = new_text.str(); | ||
104 | } | ||
105 | |||
106 | std::string Script::ToString() const { return text_; } | ||
diff --git a/script.h b/script.h new file mode 100644 index 0000000..fabf531 --- /dev/null +++ b/script.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef SCRIPT_H | ||
2 | #define SCRIPT_H | ||
3 | |||
4 | #include <filesystem> | ||
5 | #include <map> | ||
6 | #include <string> | ||
7 | #include <string_view> | ||
8 | #include <tuple> | ||
9 | #include <vector> | ||
10 | |||
11 | class Script { | ||
12 | public: | ||
13 | Script() = default; | ||
14 | |||
15 | Script(const std::filesystem::path& path, std::string_view file_prefix); | ||
16 | |||
17 | const std::vector<std::string>& loaded_scripts() const { | ||
18 | return loaded_scripts_; | ||
19 | } | ||
20 | |||
21 | const std::vector<std::tuple<std::string, int>>& exports() const { | ||
22 | return exports_; | ||
23 | } | ||
24 | |||
25 | void ReplaceScriptReferences(const std::map<std::string, int>& script_ids); | ||
26 | |||
27 | std::string ToString() const; | ||
28 | |||
29 | private: | ||
30 | std::string text_; | ||
31 | std::string file_prefix_; | ||
32 | std::vector<std::string> loaded_scripts_; | ||
33 | std::vector<std::tuple<std::string, int>> exports_; | ||
34 | }; | ||
35 | |||
36 | #endif /* SCRIPT_H */ | ||