Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
XMLParser.cpp
Go to the documentation of this file.
1
2
3#include "Headers/XMLParser.h"
4
12#include <boost/property_tree/xml_parser.hpp>
13
14namespace Divide::XML {
15
16using boost::property_tree::ptree;
17
18bool loadFromXML(IXMLSerializable& object, const ResourcePath& filePath, const char* fileName )
19{
20 return object.fromXML(filePath, fileName);
21}
22
23bool saveToXML(const IXMLSerializable& object, const ResourcePath& filePath, const char* fileName )
24{
25 return object.toXML(filePath, fileName);
26}
27
28namespace
29{
30 ptree g_emptyPtree;
31}
32
33namespace detail
34{
35 bool LoadSave::read(const ResourcePath& filePath, const char* fileName, const std::string& rootNode)
36 {
37 _filePath = filePath;
38 _fileName = fileName;
39 _rootNodePath = rootNode;
40
41 const ResourcePath loadPath = filePath / fileName;
42
43 if (!fileExists( loadPath ) || fileIsEmpty( loadPath ))
44 {
45 const FileNameAndPath data = splitPathToNameAndLocation( loadPath );
46 const FileError backupReturnCode = copyFile( data._path, (data._fileName + ".bak"), data._path, data._fileName, true);
47 if (backupReturnCode != FileError::NONE &&
48 backupReturnCode != FileError::FILE_NOT_FOUND &&
49 backupReturnCode != FileError::FILE_EMPTY)
50 {
52 {
54 }
55 }
56 }
57
58 try
59 {
60 read_xml(loadPath.string().c_str(),
61 XmlTree,
62 boost::property_tree::xml_parser::trim_whitespace);
63
64 return !XmlTree.empty();
65 }
66 catch ( const boost::property_tree::xml_parser_error& error )
67 {
68 Console::errorfn( error.what() );
69 }
70 catch(...)
71 {
73 }
74
75 return false;
76 }
77
78 bool LoadSave::write( const ResourcePath& filePath, const char* fileName ) const
79 {
80 const ResourcePath savePath = filePath / fileName;
81
82 if (fileExists(savePath))
83 {
84 const auto[file, path] = splitPathToNameAndLocation(savePath);
85
86 const FileError backupReturnCode = copyFile(path, file, path, (file + ".bak"), true);
87 if (backupReturnCode != FileError::NONE &&
88 backupReturnCode != FileError::FILE_NOT_FOUND &&
89 backupReturnCode != FileError::FILE_EMPTY)
90 {
92 }
93 }
94 else if (!createFile(savePath, true))
95 {
97 }
98
99 try
100 {
101 write_xml(savePath.string().c_str(),
102 XmlTree,
103 std::locale(),
104 boost::property_tree::xml_writer_make_settings<boost::property_tree::iptree::key_type>('\t', 1));
105
106 return true;
107 }
108 catch(const boost::property_tree::xml_parser_error& error)
109 {
110 Console::errorfn(error.what());
111 }
112 catch(...)
113 {
115 }
116
117 return false;
118 }
119}
120
121static void PopulatePressRelease(const ptree & attributes, PressReleaseActions::Entry& entryOut)
122{
123 static vector<std::string> modifiersOut, actionsUpOut, actionsDownOut;
124
125 entryOut.clear();
126 modifiersOut.resize(0);
127 actionsUpOut.resize(0);
128 actionsDownOut.resize(0);
129
130 U16 id = 0;
131
132 const std::string modifiers = attributes.get<std::string>("modifier", "");
133 if (!modifiers.empty()) {
134 Util::Split<vector<std::string>, std::string>(modifiers.c_str(), ',', modifiersOut);
135 for (const auto& it : modifiersOut) {
136 for (U8 i = 0; i < to_base(PressReleaseActions::Modifier::COUNT); ++i) {
138 entryOut.modifiers().insert(PressReleaseActions::s_modifierMappings[i]);
139 break;
140 }
141 }
142 }
143 }
144
145 const std::string actionsUp = attributes.get<std::string>("actionUp", "");
146 if (!actionsUp.empty()) {
147 Util::Split<vector<std::string>, std::string>(actionsUp.c_str(), ',', actionsUpOut);
148 for (const auto& it : actionsUpOut) {
149 if (!it.empty()) {
150 std::stringstream ss(Util::Trim(it));
151 ss >> id;
152 if (!ss.fail()) {
153 entryOut.releaseIDs().insert(id);
154 }
155 }
156 }
157 }
158
159 const std::string actionsDown = attributes.get<std::string>("actionDown", "");
160 if (!actionsDown.empty()) {
161 Util::Split<vector<std::string>, std::string>(actionsDown.c_str(), ',', actionsDownOut);
162 for (const auto& it : actionsDownOut) {
163 if (!it.empty()) {
164 std::stringstream ss(Util::Trim(it));
165 ss >> id;
166 if (!ss.fail()) {
167 entryOut.pressIDs().insert(id);
168 }
169 }
170 }
171 }
172}
173
174void loadDefaultKeyBindings(const ResourcePath& file, const Scene* scene) {
175 ptree pt;
176 Console::printfn(LOCALE_STR("XML_LOAD_DEFAULT_KEY_BINDINGS"), file);
177 read_xml(file.string().c_str(), pt);
178
179 for(const auto & [tag, data] : pt.get_child("actions", g_emptyPtree))
180 {
181 const ptree & attributes = data.get_child("<xmlattr>", g_emptyPtree);
182 scene->input()->actionList().getInputAction(attributes.get<U16>("id", 0)).displayName(attributes.get<string>("name", "").c_str());
183 }
184
186 for (const auto & [tag, data] : pt.get_child("keys", g_emptyPtree))
187 {
188 if (tag == "<xmlcomment>") {
189 continue;
190 }
191
192 const ptree & attributes = data.get_child("<xmlattr>", g_emptyPtree);
193 PopulatePressRelease(attributes, entry);
194
195 const Input::KeyCode key = Input::KeyCodeByName(Util::Trim(data.data()).c_str());
196 scene->input()->addKeyMapping(key, entry);
197 }
198
199 for (const auto & [tag, data] : pt.get_child("mouseButtons", g_emptyPtree))
200 {
201 if (tag.compare("<xmlcomment>") == 0)
202 {
203 continue;
204 }
205
206 const ptree & attributes = data.get_child("<xmlattr>", g_emptyPtree);
207 PopulatePressRelease(attributes, entry);
208
209 const Input::MouseButton btn = Input::mouseButtonByName(Util::Trim(data.data()).c_str());
210
211 scene->input()->addMouseMapping(btn, entry);
212 }
213
214 const std::string label("joystickButtons.joystick");
215 for (U32 i = 0 ; i < to_base(Input::Joystick::COUNT); ++i) {
216 const Input::Joystick joystick = static_cast<Input::Joystick>(i);
217
218 for (const auto & [tag, value] : pt.get_child(label + std::to_string(i + 1), g_emptyPtree))
219 {
220 if ( tag.compare( "<xmlcomment>" ) == 0 )
221 {
222 continue;
223 }
224
225 const ptree & attributes = value.get_child("<xmlattr>", g_emptyPtree);
226 PopulatePressRelease(attributes, entry);
227
228 const Input::JoystickElement element = Input::joystickElementByName(Util::Trim(value.data()).c_str());
229
230 scene->input()->addJoystickMapping(joystick, element._type, element._elementIndex, entry);
231 }
232 }
233}
234
235void loadMusicPlaylist(const ResourcePath& scenePath, const Str<64>& fileName, Scene* scene, [[maybe_unused]] const Configuration& config)
236{
237 const ResourcePath file = scenePath / fileName;
238
239 if (!fileExists(file))
240 {
241 return;
242 }
243
244 Console::printfn(LOCALE_STR("XML_LOAD_MUSIC"), file);
245
246 ptree pt;
247 read_xml(file.string().c_str(), pt);
248
249 for (const auto & [tag, data] : pt.get_child("backgroundThemes", g_emptyPtree))
250 {
251 const ptree & attributes = data.get_child("<xmlattr>", g_emptyPtree);
253 attributes.get<string>("name", "").c_str(),
254 Paths::g_assetsLocation / attributes.get<string>("src", "") );
255 }
256}
257
258void writeXML(const ResourcePath& path, const ptree& tree)
259{
260 static boost::property_tree::xml_writer_settings<std::string> settings(' ', 4);
261
262 write_xml(path.string().c_str(), tree, std::locale(), settings);
263}
264
265void readXML(const ResourcePath& path, ptree& tree)
266{
267 try
268 {
269 read_xml(path.string().c_str(), tree);
270 }
271 catch (const boost::property_tree::xml_parser_error& e)
272 {
273 Console::errorfn(LOCALE_STR("ERROR_XML_INVALID_FILE"), path, e.what());
274 }
275}
276} // namespace Divide::XML
#define LOCALE_STR(X)
Definition: Localization.h:91
#define DIVIDE_UNEXPECTED_CALL()
static constexpr Input::KeyCode s_modifierMappings[to_base(Modifier::COUNT)]
static constexpr const char * s_modifierNames[to_base(Modifier::COUNT)]
void addMusic(MusicType type, const std::string_view name, const ResourcePath &srcFile)
Definition: Scene.cpp:167
constexpr bool IS_SHIPPING_BUILD
Definition: config.h:60
Joystick
Points to the position of said joystick in the vector.
Definition: Input.h:39
MouseButton mouseButtonByName(const string &buttonName)
JoystickElement joystickElementByName(const string &elementName)
KeyCode KeyCodeByName(const char *keyName) noexcept
Definition: Input.cpp:146
T_str & Trim(T_str &s)
bool loadFromXML(IXMLSerializable &object, const ResourcePath &filePath, const char *fileName)
Definition: XMLParser.cpp:18
bool saveToXML(const IXMLSerializable &object, const ResourcePath &filePath, const char *fileName)
Definition: XMLParser.cpp:23
void loadDefaultKeyBindings(const ResourcePath &file, const Scene *scene)
Child Functions.
Definition: XMLParser.cpp:174
void loadMusicPlaylist(const ResourcePath &scenePath, const Str< 64 > &fileName, Scene *scene, const Configuration &config)
Definition: XMLParser.cpp:235
static void PopulatePressRelease(const ptree &attributes, PressReleaseActions::Entry &entryOut)
Definition: XMLParser.cpp:121
void writeXML(const ResourcePath &path, const boost::property_tree::ptree &tree)
void readXML(const ResourcePath &path, boost::property_tree::ptree &tree)
uint8_t U8
eastl::vector< Type > vector
Definition: Vector.h:42
FileError copyFile(const ResourcePath &sourcePath, const std::string_view sourceName, const ResourcePath &targetPath, const std::string_view targetName, const bool overwrite)
bool fileIsEmpty(const ResourcePath &filePathAndName)
uint16_t U16
bool fileExists(const ResourcePath &filePathAndName)
uint32_t U32
Project const SceneEntry & entry
Definition: DefaultScene.h:41
FileNameAndPath splitPathToNameAndLocation(const ResourcePath &input)
bool createFile(const ResourcePath &filePathAndName, const bool overwriteExisting)
constexpr auto to_base(const Type value) -> Type
static NO_INLINE void errorfn(const char *format, T &&... args)
static NO_INLINE void printfn(const char *format, T &&... args)
JoystickElementType _type
Definition: Input.h:85
void clear() noexcept
StringReturnType< N > string() const noexcept
Definition: ResourcePath.h:64
bool write(const ResourcePath &filePath, const char *fileName) const
Definition: XMLParser.cpp:78
boost::property_tree::iptree XmlTree
Definition: XMLParser.h:56
bool read(const ResourcePath &filePath, const char *fileName, const std::string &rootNode)
Definition: XMLParser.cpp:35