diff options
author | Aki <please@ignore.pl> | 2022-04-10 20:01:38 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2022-04-10 20:55:52 +0200 |
commit | 014ec9abb825fc91366ae54945187d01e2c92e55 (patch) | |
tree | 4ba7f305bcb4bae3fe0707102b8ef4d39161d42a /StarsEx/DataSource.cpp | |
parent | 879612a1dcb6bb5b891447baffd4d5917ea37ee5 (diff) | |
download | starshatter-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.cpp | 166 |
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; +} |