summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Hall <mewaysid92@gmail.com>2025-07-03 20:27:12 +0000
committerAndrew Hall <mewaysid92@gmail.com>2025-07-03 20:27:12 +0000
commitb3f73ec6e4a71272317bbbde18c384ac87a0af71 (patch)
tree1d356a9973c14aab802f84424a7a95218d76da8e
parent7efaf3fab992f7fd4a9dc101bcb40d8547188a4b (diff)
downloadverse-b3f73ec6e4a71272317bbbde18c384ac87a0af71.tar.gz
verse-b3f73ec6e4a71272317bbbde18c384ac87a0af71.tar.bz2
verse-b3f73ec6e4a71272317bbbde18c384ac87a0af71.tar.xz
verse-b3f73ec6e4a71272317bbbde18c384ac87a0af71.zip
Update 4 files
- /src/utils/filesystem.h - /src/utils/xml.cpp - /src/utils/xml.h - /src/log.h
-rw-r--r--src/log.h72
-rw-r--r--src/utils/filesystem.h297
-rw-r--r--src/utils/xml.cpp15
-rw-r--r--src/utils/xml.h26
4 files changed, 403 insertions, 7 deletions
diff --git a/src/log.h b/src/log.h
new file mode 100644
index 000000000..f4f78fa11
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,72 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2012 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <fstream>
+
+/**
+ * The Log Class : Useful to write debug or info messages
+ */
+class Logger
+{
+ public:
+ Logger();
+
+ /**
+ * Destructor, closes log file.
+ */
+ ~Logger();
+
+ /**
+ * Sets the file to log to and opens it
+ */
+ void setLogFile(const std::string &logFilename);
+
+ /**
+ * Sets whether the log should be written to standard output.
+ */
+ void setLogToStandardOut(bool value) { mLogToStandardOut = value; }
+
+ /**
+ * Enters a message in the log. The message will be timestamped.
+ */
+ void log(const char *log_text, ...)
+#ifdef __GNUC__
+ __attribute__((__format__(__printf__, 2, 3)))
+#endif
+ ;
+
+ void vlog(const char *log_text, va_list ap);
+
+ /**
+ * Log an error and quit. The error will be printed to standard error
+ * and showm in a simple message box.
+ */
+ __attribute__((noreturn))
+ void error(const std::string &error_text);
+
+ private:
+ std::ofstream mLogFile;
+ bool mLogToStandardOut = true;
+};
+
+extern Logger *logger;
diff --git a/src/utils/filesystem.h b/src/utils/filesystem.h
new file mode 100644
index 000000000..3474e7c49
--- /dev/null
+++ b/src/utils/filesystem.h
@@ -0,0 +1,297 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2024 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+// Suppress deprecation warnings for PHYSFS_getUserDir
+#define PHYSFS_DEPRECATED
+
+#include "utils/physfsrwops.h"
+
+#include <optional>
+#include <string>
+
+/**
+ * These functions wrap PHYSFS functions to provide a more user-friendly
+ * interface and to limit the direct use of the PHYSFS API to a single file.
+ */
+namespace FS {
+
+inline bool init(const char *argv0)
+{
+ return PHYSFS_init(argv0) != 0;
+}
+
+inline void deinit()
+{
+ PHYSFS_deinit();
+}
+
+inline const char *getDirSeparator()
+{
+ return PHYSFS_getDirSeparator();
+}
+
+inline const char *getBaseDir()
+{
+ return PHYSFS_getBaseDir();
+}
+
+inline const char *getUserDir()
+{
+ return PHYSFS_getUserDir();
+}
+
+inline const char *getPrefDir(const char *org, const char *app)
+{
+ return PHYSFS_getPrefDir(org, app);
+}
+
+/**
+ * Sets the write directory.
+ *
+ * @param path The path of the directory to be added.
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+inline bool setWriteDir(const std::string &path)
+{
+ return PHYSFS_setWriteDir(path.c_str()) != 0;
+}
+
+/**
+ * Adds a directory or archive to the search path. If append is true
+ * then the directory is added to the end of the search path, otherwise
+ * it is added at the front.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+inline bool addToSearchPath(const std::string &path, bool append)
+{
+ return PHYSFS_mount(path.c_str(), "/", append ? 1 : 0) != 0;
+}
+
+/**
+ * Checks whether the given file or directory exists in the search path.
+ */
+inline bool exists(const std::string &path)
+{
+ return PHYSFS_exists(path.c_str()) != 0;
+}
+
+inline std::optional<const char *> getRealDir(const std::string &path)
+{
+ auto dir = PHYSFS_getRealDir(path.c_str());
+ return dir ? std::optional<const char *>(dir) : std::nullopt;
+}
+
+/**
+ * Checks whether the given path is a directory.
+ */
+inline bool isDirectory(const std::string &path)
+{
+ PHYSFS_Stat stat;
+ if (PHYSFS_stat(path.c_str(), &stat) != 0)
+ {
+ return stat.filetype == PHYSFS_FILETYPE_DIRECTORY;
+ }
+ return false;
+}
+
+/**
+ * Creates a directory in the write path.
+ */
+inline bool mkdir(const std::string &path)
+{
+ return PHYSFS_mkdir(path.c_str()) != 0;
+}
+
+/**
+ * Helper class to iterate over the files in a directory.
+ * Based on https://stackoverflow.com/a/79051293/355419.
+ */
+class Files
+{
+public:
+ struct End {};
+ friend bool operator!=(const char *const *files, End)
+ { return *files != nullptr; }
+
+ explicit Files(char **files) : mFiles(files) {}
+ ~Files() { PHYSFS_freeList(mFiles); }
+
+ Files(const Files &) = delete;
+ Files &operator=(const Files &) = delete;
+
+ // Relies on C++17 support for begin/end to not have the same return type
+ const char* const *begin() const { return mFiles; }
+ End end() const { return End(); }
+
+private:
+ char **mFiles;
+};
+
+/**
+ * Returns a list of files in the given directory.
+ */
+inline Files enumerateFiles(const std::string &dir)
+{
+ return Files(PHYSFS_enumerateFiles(dir.c_str()));
+}
+
+/**
+ * File wrapper class to provide a more convenient API and automatic closing.
+ */
+class File
+{
+public:
+ explicit File(PHYSFS_file *file)
+ : file(file)
+ {}
+
+ ~File()
+ {
+ if (isOpen())
+ close();
+ }
+
+ bool isOpen() const
+ {
+ return file != nullptr;
+ }
+
+ operator bool() const
+ {
+ return isOpen();
+ }
+
+ bool close()
+ {
+ if (PHYSFS_close(file) != 0)
+ {
+ file = nullptr;
+ return true;
+ }
+ return false;
+ }
+
+ std::optional<size_t> read(void *data, size_t size)
+ {
+ auto len = PHYSFS_readBytes(file, data, size);
+ return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
+ }
+
+ std::optional<size_t> write(const void *data, size_t size)
+ {
+ auto len = PHYSFS_writeBytes(file, data, size);
+ return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
+ }
+
+ bool flush()
+ {
+ return PHYSFS_flush(file) != 0;
+ }
+
+ bool seek(size_t pos)
+ {
+ return PHYSFS_seek(file, pos) != 0;
+ }
+
+ std::optional<size_t> fileLength() const
+ {
+ auto len = PHYSFS_fileLength(file);
+ return len >= 0 ? std::optional<size_t>(len) : std::nullopt;
+ }
+
+ std::optional<size_t> tell() const
+ {
+ auto pos = PHYSFS_tell(file);
+ return pos >= 0 ? std::optional<size_t>(pos) : std::nullopt;
+ }
+
+ bool eof() const
+ {
+ return PHYSFS_eof(file) != 0;
+ }
+
+private:
+ PHYSFS_file *file;
+};
+
+inline File openWrite(const std::string &path)
+{
+ return File(PHYSFS_openWrite(path.c_str()));
+}
+
+inline File openAppend(const std::string &path)
+{
+ return File(PHYSFS_openAppend(path.c_str()));
+}
+
+inline File openRead(const std::string &path)
+{
+ return File(PHYSFS_openRead(path.c_str()));
+}
+
+inline const char *getLastError()
+{
+ return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
+}
+
+//
+// Helper functions for loading files through SDL_RWops
+//
+
+inline SDL_RWops *openRWops(const std::string &path)
+{
+ return PHYSFSRWOPS_openRead(path.c_str());
+}
+
+/**
+ * Creates a buffered SDL_RWops.
+ *
+ * Used to workaround a performance issue when SDL_mixer is using stb_vorbis,
+ * in which case the file is read one byte at a time.
+ *
+ * See https://github.com/libsdl-org/SDL_mixer/issues/670
+ */
+inline SDL_RWops *openBufferedRWops(const std::string &path,
+ PHYSFS_uint64 bufferSize = 2048)
+{
+ if (auto file = PHYSFS_openRead(path.c_str()))
+ {
+ PHYSFS_setBuffer(file, bufferSize);
+ if (auto rw = PHYSFSRWOPS_makeRWops(file))
+ return rw;
+ else
+ PHYSFS_close(file);
+ }
+ return nullptr;
+}
+
+inline void *loadFile(const std::string &path, size_t &datasize)
+{
+ auto file = openRWops(path);
+ if (!file)
+ return nullptr;
+
+ return SDL_LoadFile_RW(file, &datasize, 1);
+}
+
+} // namespace FS
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index c408c9c2e..8ade4e5d8 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -1,9 +1,9 @@
/*
- * The Mana Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * The ManaVerse Client
+ * Copyright (C) 2011-2020 The ManaPlus Developers
+ * Copyright (C) 2020-2025 The ManaVerse Developers
*
- * This file is part of The Mana Client.
+ * This file is part of The ManaVerse Client.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,13 +18,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "debug.h"
+
+#include "src/log.h"
#include "utils/xml.h"
#include <libxml/xmlerror.h>
-#include "log.h"
-
#include "utils/filesystem.h"
namespace XML
@@ -55,7 +56,7 @@ namespace XML
xmlCtxtResetLastError(error->ctxt);
}
- Document::Document(const std::string &filename, bool useResman):
+ Document::Document(const std::string &filename, bool useResman) :
mDoc(nullptr)
{
XMLContext ctx;
diff --git a/src/utils/xml.h b/src/utils/xml.h
index 16084bde5..44995de58 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -33,3 +33,29 @@
XML_INCLUDE_DEFINE
#endif // UTILS_XML_H
+
+namespace XML
+{
+ void init();
+
+ class Document final
+ {
+ public:
+ explicit Document(const std::string &filename, bool useResman);
+ ~Document();
+
+ xmlDocPtr mDoc;
+ };
+
+ class Writer final
+ {
+ public:
+ explicit Writer(const std::string &fileName);
+ ~Writer();
+
+ xmlTextWriterPtr mWriter;
+ };
+} // namespace XML
+
+#endif // UTILS_XML_H
+