summaryrefslogtreecommitdiffhomepage
path: root/StarsEx/DataSource.cpp
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/DataSource.cpp
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/DataSource.cpp')
-rw-r--r--StarsEx/DataSource.cpp166
1 files changed, 166 insertions, 0 deletions
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;
+}