Skip to content

Commit

Permalink
Import files.
Browse files Browse the repository at this point in the history
  • Loading branch information
stuart6854 committed Nov 27, 2023
1 parent bdcb7f2 commit ddded81
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 14 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,26 @@ gfs::MountID mountId = dataMount;
std::filesystem::path filename = "archive_file.pbin";
std::vector<gfs::FileID> files{ 98475845, 111, 222, 666 };
bool wasCreated = fs.CreateArchive(mountId, filename, files);

/* Import files */
struct MyImporter : gfs::FileImporter
{
bool Import(gfs::Filesystem& fs, const std::filesystem::path& importFilename, gfs::MountID outputMount, const std::filesystem::path& outputDir) override
{
...
}

bool Reimport(gfs::Filesystem& fs, const gfs::Filesystem::File& file) override
{
...
}
};
fs.SetImporter({ ".txt", ".ext" }, std::make_shared<MyImporter>());
bool wasImported = fs.Import("path/to/external/file.txt", mountId, "mount/rel/output/dir/");
bool wasReimported = fs.Reimport(fileId);

```
## Planned Features
- Add data compression threshold eg. only compress data greater than ~0.5MB
- File importing - Call Filesystem::ImportFile(filename) which gets a FileImporter assigned to file ext and reads, processes and writes a new file
- Files that were imported track the source filename - allows for reimport, which would potentially allow for asset/resource hot-reloading
- Add data compression threshold eg. only compress data greater than ~0.5MB
17 changes: 9 additions & 8 deletions include/gfs/file_importer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

namespace gfs
{
class FileImporter
{
public:
virtual ~FileImporter() = default;
class FileImporter
{
public:
virtual ~FileImporter() = default;

virtual bool Import(const std::filesystem::path& importFilename, const std::filesystem::path& outputDir) = 0;
virtual bool Reimport(const Filesystem::File& file) = 0;
};
}
virtual bool Import(Filesystem& fs, const std::filesystem::path& importFilename, MountID outputMount, const std::filesystem::path& outputDir) = 0;
virtual bool Reimport(Filesystem& fs, const Filesystem::File& file) = 0;
};

} // namespace gfs
8 changes: 7 additions & 1 deletion include/gfs/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ namespace gfs
FileID FileId; // The Unique Identifier of the file.
MountID MountId; // The Id of the mount this file is in.
std::filesystem::path MountRelPath; // Path to this file relative to the mount it is in.
std::filesystem::path SourceFilename; // The source file this file was imported from.
std::vector<FileID> FileDependencies; // Files this file references.
uint32_t UncompressedSize;
uint32_t CompressedSize;
Expand Down Expand Up @@ -132,7 +133,8 @@ namespace gfs
FileID fileId,
const std::vector<FileID>& fileDependencies,
const BinaryStreamable& dataObject,
bool compress);
bool compress,
const std::filesystem::path& sourceFilename = "");

/**
* @brief
Expand Down Expand Up @@ -166,6 +168,10 @@ namespace gfs
*/
auto GetImporter(const std::string& fileExt) -> std::shared_ptr<FileImporter>;

bool Import(const std::filesystem::path& filename, MountID outputMount, const std::filesystem::path& outputDir);

bool Reimport(FileID fileId);

//////////////////////////////////////////////////////////////////////////
// Utility
//////////////////////////////////////////////////////////////////////////
Expand Down
52 changes: 50 additions & 2 deletions src/gfs/filesystem.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "gfs/filesystem.hpp"
#include "gfs/binary_streams.hpp"
#include "gfs/file_importer.hpp"

#include <cstdint>
#include <filesystem>
#include <functional>
#include <lz4.h>

#include <cstdint>
#include <cassert>
#include <fstream>
#include <iostream>
Expand Down Expand Up @@ -87,7 +90,8 @@ namespace gfs
FileID fileId,
const std::vector<FileID>& fileDependencies,
const BinaryStreamable& dataObject,
bool compress)
bool compress,
const std::filesystem::path& sourceFilename)
{
auto* mount = GetMount(mountId);
if (!mount)
Expand Down Expand Up @@ -121,6 +125,7 @@ namespace gfs
file.FileId = fileId;
file.MountId = mountId;
file.MountRelPath = filename;
file.SourceFilename = sourceFilename;
file.FileDependencies = fileDependencies;
file.UncompressedSize = uint32_t(uncompressedDataBuffer.GetSize());
file.CompressedSize = uint32_t(compressedDataBuffer.GetSize());
Expand Down Expand Up @@ -285,6 +290,36 @@ namespace gfs
return it->second;
}

bool Filesystem::Import(const std::filesystem::path& filename, MountID outputMount, const std::filesystem::path& outputDir)
{
if (filename.empty() || !std::filesystem::exists(filename) || !std::filesystem::is_regular_file(filename))
return false;

const auto fileExt = filename.extension();
auto importer = GetImporter(fileExt);
if (!importer)
return false;

return importer->Import(*this, filename, outputMount, outputDir);
}

bool Filesystem::Reimport(FileID fileId)
{
auto* file = GetFile(fileId);
if (!file)
return false;

if (file->SourceFilename.empty() || !std::filesystem::exists(file->SourceFilename) || !std::filesystem::is_regular_file(file->SourceFilename))
return false;

const auto fileExt = file->SourceFilename.extension();
auto importer = GetImporter(fileExt);
if (!importer)
return false;

return importer->Reimport(*this, *file);
}

bool Filesystem::IsPathInMount(const std::filesystem::path& path, MountID mountId)
{
auto* mount = GetMount(mountId);
Expand Down Expand Up @@ -409,6 +444,12 @@ namespace gfs
auto pathStr = file.MountRelPath.string();
stream.write(reinterpret_cast<const char*>(pathStr.data()), strLen);

// Source filename
strLen = file.SourceFilename.string().size();
stream.write(reinterpret_cast<const char*>(&strLen), sizeof(strLen));
pathStr = file.SourceFilename.string();
stream.write(reinterpret_cast<const char*>(pathStr.data()), strLen);

// File dependencies
const auto count = uint16_t(file.FileDependencies.size());
stream.write(reinterpret_cast<const char*>(&count), sizeof(count));
Expand All @@ -432,6 +473,13 @@ namespace gfs
stream.read(reinterpret_cast<char*>(pathStr.data()), strLen);
file.MountRelPath = pathStr;

// Source filename
strLen = 0;
stream.read(reinterpret_cast<char*>(&strLen), sizeof(strLen));
pathStr = std::string(strLen, 0);
stream.read(reinterpret_cast<char*>(pathStr.data()), strLen);
file.SourceFilename = pathStr;

// File dependencies
uint16_t count = 0;
stream.read(reinterpret_cast<char*>(&count), sizeof(count));
Expand Down
36 changes: 36 additions & 0 deletions testbed/testbed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <cstring>
Expand Down Expand Up @@ -54,6 +55,29 @@ struct TextResource : gfs::BinaryStreamable
void Write(gfs::WriteOnlyByteBuffer& buffer) const override { buffer.Write(Text); }
};

struct TextFileImporter : gfs::FileImporter
{
bool Import(gfs::Filesystem& fs, const std::filesystem::path& importFilename, gfs::MountID outputMount, const std::filesystem::path& outputDir) override
{
auto text = ReadTextFile(importFilename);
if (text.empty())
return false;

TextResource resource{};
resource.Text = text;

auto outputFilename = outputDir / importFilename.filename();
outputFilename.replace_extension(".rbin");

const auto fileId = std::hash<std::filesystem::path>{}(importFilename);
fs.WriteFile(outputMount, outputFilename, fileId, {}, resource, resource.Text.size() >= 524288, importFilename);

return true;
}

bool Reimport(gfs::Filesystem& fs, const gfs::Filesystem::File& file) override { return false; }
};

int main()
{
std::cout << "GFS Testbed\n";
Expand Down Expand Up @@ -147,6 +171,18 @@ int main()
}
}

{
// Importing
fs.SetImporter({ ".txt" }, std::make_shared<TextFileImporter>());
if (!fs.Import("external_files/txt_file.txt", mountA, ""))
assert(false);

TextResource importedFile{};
if (!fs.ReadFile(5319311783236469214, importedFile))
assert(false);
assert(importedFile.Text == shortText.Text);
}

std::cout << "Files" << std::endl;
fs.ForEachFile([](const gfs::Filesystem::File& file) { std::cout << "- " << file.FileId << " - " << file.MountRelPath << std::endl; });

Expand Down

0 comments on commit ddded81

Please sign in to comment.