summaryrefslogtreecommitdiffhomepage
path: root/StarsEx
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-04-10 20:01:38 +0200
committerAki <please@ignore.pl>2022-04-10 20:55:52 +0200
commit014ec9abb825fc91366ae54945187d01e2c92e55 (patch)
tree4ba7f305bcb4bae3fe0707102b8ef4d39161d42a /StarsEx
parent879612a1dcb6bb5b891447baffd4d5917ea37ee5 (diff)
downloadstarshatter-014ec9abb825fc91366ae54945187d01e2c92e55.zip
starshatter-014ec9abb825fc91366ae54945187d01e2c92e55.tar.gz
starshatter-014ec9abb825fc91366ae54945187d01e2c92e55.tar.bz2
Added simple DataSources to replace parts of DataLoader
Diffstat (limited to 'StarsEx')
-rw-r--r--StarsEx/CMakeLists.txt1
-rw-r--r--StarsEx/DataLoader.cpp35
-rw-r--r--StarsEx/DataLoader.h5
-rw-r--r--StarsEx/DataSource.cpp166
-rw-r--r--StarsEx/DataSource.h64
5 files changed, 270 insertions, 1 deletions
diff --git a/StarsEx/CMakeLists.txt b/StarsEx/CMakeLists.txt
index 290c81c..07bb940 100644
--- a/StarsEx/CMakeLists.txt
+++ b/StarsEx/CMakeLists.txt
@@ -63,6 +63,7 @@ add_library(
CtlDlg.cpp
D3DXImage.cpp
DataLoader.cpp
+ DataSource.cpp
DebriefDlg.cpp
Debris.cpp
DetailSet.cpp
diff --git a/StarsEx/DataLoader.cpp b/StarsEx/DataLoader.cpp
index 72eaf4b..1dcbe0e 100644
--- a/StarsEx/DataLoader.cpp
+++ b/StarsEx/DataLoader.cpp
@@ -26,11 +26,13 @@ DataLoader* DataLoader::loader = 0;
DataLoader::DataLoader()
: datapath(""), video(0), use_file_system(true), enable_media(true)
-{ }
+{
+}
DataLoader::~DataLoader()
{
archives.destroy();
+ sources.destroy();
}
// +--------------------------------------------------------------------+
@@ -82,6 +84,37 @@ DataLoader::EnableMedia(bool enable)
// +--------------------------------------------------------------------+
int
+DataLoader::InsertDatafile(const char* name, int pos)
+{
+ FILE* f = fopen(name, "rb");
+ if (!f) {
+ Print(" WARNING: could not open datafile '%s'\n", name);
+ return DATAFILE_NOTEXIST;
+ }
+ fclose(f);
+ auto archive = new DataArchive(name);
+ if (!archive || archive->NumFiles() < 1) {
+ Print(" WARNING: invalid data file '%s'\n", name);
+ if (archive) delete archive;
+ return DATAFILE_INVALID;
+ }
+ DataSource* source = new ArchiveDataSource(archive);
+ if (pos < 0)
+ sources.append(source);
+ else
+ sources.insert(source, pos);
+ return DATAFILE_OK;
+}
+
+void
+DataLoader::ClearSources()
+{
+ sources.destroy();
+}
+
+// +--------------------------------------------------------------------+
+
+int
DataLoader::EnableDatafile(const char* name)
{
int status = DATAFILE_NOTEXIST;
diff --git a/StarsEx/DataLoader.h b/StarsEx/DataLoader.h
index eaf4f28..81098e8 100644
--- a/StarsEx/DataLoader.h
+++ b/StarsEx/DataLoader.h
@@ -11,6 +11,7 @@
#define DataLoader_h
#include "Archive.h"
+#include "DataSource.h"
#include "Types.h"
#include "List.h"
#include "Text.h"
@@ -42,6 +43,9 @@ public:
void UseVideo(Video* v);
void EnableMedia(bool enable=true);
+ int InsertDatafile(const char* name, int pos=-1);
+ void ClearSources();
+
int EnableDatafile(const char* name);
int DisableDatafile(const char* name);
@@ -79,6 +83,7 @@ private:
bool enable_media;
List<DataArchive> archives;
+ List<DataSource> sources;
static DataLoader* loader;
};
diff --git a/StarsEx/DataSource.cpp b/StarsEx/DataSource.cpp
new file mode 100644
index 0000000..b587971
--- /dev/null
+++ b/StarsEx/DataSource.cpp
@@ -0,0 +1,166 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#include "DataSource.h"
+
+#include <cstdint>
+#include <cstring>
+#include <filesystem>
+
+#include "Archive.h"
+#include "List.h"
+#include "Text.h"
+
+
+DataSource::DataSource() :
+ m_prefix {""}
+{
+}
+
+
+DataSource::~DataSource()
+{
+}
+
+
+void
+DataSource::SetPrefix(const char* prefix)
+{
+ if (prefix)
+ m_prefix = prefix;
+ else
+ m_prefix = "";
+}
+
+
+ArchiveDataSource::ArchiveDataSource(const char* name) :
+ ArchiveDataSource(new DataArchive(name))
+{
+}
+
+
+ArchiveDataSource::ArchiveDataSource(DataArchive* archive) :
+ m_archive {archive}
+{
+}
+
+
+ArchiveDataSource::~ArchiveDataSource()
+{
+ delete m_archive;
+}
+
+
+bool
+ArchiveDataSource::Find(const char* name) const
+{
+ const int index = m_archive->FindEntry(name);
+ return index > -1;
+}
+
+
+int
+ArchiveDataSource::ListFiles(Text filter, List<Text>& items, bool recurse) const
+{
+ (void) recurse; // Lookup in DataArchives was always recursive so far
+ filter = filter.replace("*", ""); // Wildcards worked only on boundaries
+ const int prefix = m_prefix.length();
+ const int count = m_archive->NumFiles();
+ for (int i = 0; i < count; ++i) {
+ const auto* entry = m_archive->GetFile(i);
+ Text name = entry->name;
+ name.setSensitive(false);
+ if (name.contains(m_prefix) && name.contains(filter)) {
+ const auto without_prefix = name.substring(prefix, name.length());
+ if (!items.contains(&without_prefix))
+ items.append(new Text(without_prefix));
+ }
+ }
+ return items.size();
+}
+
+
+int
+ArchiveDataSource::Load(const char* name, std::uint8_t*& buf, bool null_terminate) const
+{
+ const int index = m_archive->FindEntry(name);
+ if (index > -1)
+ return m_archive->ExpandEntry(index, buf, null_terminate);
+ return 0; // -1 would be preferable, but 0 is from legacy
+}
+
+
+FileSystemDataSource::FileSystemDataSource(const char* path) :
+ m_path {path}
+{
+}
+
+
+FileSystemDataSource::~FileSystemDataSource()
+{
+}
+
+
+bool
+FileSystemDataSource::Find(const char* name) const
+{
+ std::filesystem::path full_path {m_path};
+ full_path.append(m_prefix.data());
+ full_path.append(name);
+ return std::filesystem::is_regular_file(full_path);
+}
+
+
+int
+FileSystemDataSource::ListFiles(Text filter, List<Text>& items, bool recurse) const
+{
+ std::filesystem::path full_path {m_path};
+ full_path.append(m_prefix.data());
+ filter = filter.replace("*", "");
+ const auto check = [&items, &filter](const std::filesystem::directory_entry& entry){
+ const auto filename = entry.path().filename().string();
+ const auto index = filename.find(filter.data());
+ if (index != decltype(filename)::npos)
+ items.append(new Text(entry.path().string().c_str()));
+ };
+ if (recurse) {
+ for (const auto& entry : std::filesystem::recursive_directory_iterator(full_path))
+ check(entry);
+ }
+ else {
+ for (const auto& entry : std::filesystem::directory_iterator(full_path))
+ check(entry);
+ }
+ return items.size();
+}
+
+
+int
+FileSystemDataSource::Load(const char* name, std::uint8_t*& buf, bool null_terminate) const
+{
+ std::filesystem::path full_path {m_path};
+ full_path.append(m_prefix.data());
+ full_path.append(name);
+ FILE* f = fopen(full_path.string().c_str(), "rb");
+ if (!f)
+ return 0; // Again, -1 would be better to differentiate an error from an empty file
+ fseek(f, 0, SEEK_END);
+ int length = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ if (null_terminate) {
+ buf = new std::uint8_t[length + 1];
+ if (buf)
+ buf[length] = 0;
+ }
+ else {
+ buf = new std::uint8_t[length];
+ }
+ int bytes = 0;
+ if (buf)
+ bytes = fread(buf, length, 1, f);
+ fclose(f);
+ return bytes;
+}
diff --git a/StarsEx/DataSource.h b/StarsEx/DataSource.h
new file mode 100644
index 0000000..3da58ca
--- /dev/null
+++ b/StarsEx/DataSource.h
@@ -0,0 +1,64 @@
+/* Starshatter: The Open Source Project
+ Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
+ Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
+ Copyright (c) 1997-2006, Destroyer Studios LLC.
+*/
+
+#ifndef DataSource_h
+#define DataSource_h
+
+#include <cstdint>
+
+#include "Archive.h"
+#include "List.h"
+#include "Text.h"
+
+
+class DataSource
+{
+public:
+ DataSource();
+ virtual ~DataSource();
+
+ virtual void SetPrefix(const char* prefix=nullptr);
+ virtual bool Find(const char* name) const = 0;
+ virtual int ListFiles(Text filter, List<Text>& items, bool recurse=false) const = 0;
+ virtual int Load(const char* name, std::uint8_t*& buf, bool null_terminate=false) const = 0;
+
+protected:
+ Text m_prefix;
+};
+
+
+class ArchiveDataSource : public DataSource
+{
+public:
+ explicit ArchiveDataSource(const char* name);
+ explicit ArchiveDataSource(DataArchive* archive);
+ ~ArchiveDataSource() override;
+
+ bool Find(const char* name) const override;
+ int ListFiles(Text filter, List<Text>& items, bool recurse=false) const override;
+ int Load(const char* name, std::uint8_t*& buf, bool null_terminate=false) const override;
+
+protected:
+ DataArchive* m_archive;
+};
+
+
+class FileSystemDataSource : public DataSource
+{
+public:
+ explicit FileSystemDataSource(const char* path="");
+ ~FileSystemDataSource() override;
+
+ bool Find(const char* name) const override;
+ int ListFiles(Text filter, List<Text>& items, bool recurse=false) const override;
+ int Load(const char* name, std::uint8_t*& buf, bool null_terminate=false) const override;
+
+protected:
+ const char* m_path;
+};
+
+
+#endif // DataSource_h