From 014ec9abb825fc91366ae54945187d01e2c92e55 Mon Sep 17 00:00:00 2001 From: Aki Date: Sun, 10 Apr 2022 20:01:38 +0200 Subject: Added simple DataSources to replace parts of DataLoader --- StarsEx/CMakeLists.txt | 1 + StarsEx/DataLoader.cpp | 35 ++++++++++- StarsEx/DataLoader.h | 5 ++ StarsEx/DataSource.cpp | 166 +++++++++++++++++++++++++++++++++++++++++++++++++ StarsEx/DataSource.h | 64 +++++++++++++++++++ 5 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 StarsEx/DataSource.cpp create mode 100644 StarsEx/DataSource.h (limited to 'StarsEx') 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 archives; + List 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 +#include +#include + +#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& 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& 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 + +#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& 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& 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& 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 -- cgit v1.1