Skip to content

Commit

Permalink
Added an option to filter files based on size
Browse files Browse the repository at this point in the history
  • Loading branch information
hhyyrylainen committed Jul 4, 2020
1 parent ab37ddd commit e9c07b1
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 6 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.10)
project(GodotPckTool)

set(GODOT_PCK_TOOL_VERSION_MAJOR 1)
set(GODOT_PCK_TOOL_VERSION_MINOR 3)
set(GODOT_PCK_TOOL_VERSION_MINOR 4)

set(GODOT_PCK_TOOL_VERSION_STR "${GODOT_PCK_TOOL_VERSION_MAJOR}.${GODOT_PCK_TOOL_VERSION_MINOR}")

Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,38 @@ Long form:
godotpcktool --pack Thrive.pck --action add --remove-prefix extracted --file extracted
```

### Filters

Filters can be used to only act on a subset of files in a pck file, or
from the filesystem.

#### Min size

Specify the minimum size under which files are excluded:

```sh
godotpcktool --min-size-filter 1000
```

This will exclude files with size 999 bytes and below.

### Max size

Specify the maximum size above which files are excluded:

```sh
godotpcktool --max-size-filter 1000
```

NOTE: if you use max size to compliment min size extraction, you
should subtract one from the size, otherwise you'll operate on the
same files twice.

However if you want to work on exactly some size files you can specify the same size twice:
```sh
godotpcktool --min-size-filter 1 --max-size-filter 1
```

### General info

In the long form multiple files may be included like this:
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_library(pck
pck/PckFile.h pck/PckFile.cpp
PckTool.h PckTool.cpp
FileFilter.h FileFilter.cpp
Include.h Define.h
)

Expand Down
17 changes: 17 additions & 0 deletions src/FileFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ------------------------------------ //
#include "FileFilter.h"

using namespace pcktool;
// ------------------------------------ //
bool FileFilter::Include(const PckFile::ContainedFile& file)
{
if(file.Size < MinSizeLimit)
return false;

if(file.Size > MaxSizeLimit)
return false;

// Wasn't excluded
return true;
}
// ------------------------------------ //
33 changes: 33 additions & 0 deletions src/FileFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "Define.h"

#include "pck/PckFile.h"

namespace pcktool {

//! \brief An include / exclude filter for files
class FileFilter {
public:
//! \returns true if filter doesn't exclude a file
bool Include(const PckFile::ContainedFile& file);

void SetSizeMinLimit(uint64_t size)
{
MinSizeLimit = size;
}

void SetSizeMaxLimit(uint64_t size)
{
MaxSizeLimit = size;
}

private:
//! File is excluded if it is under this size
uint64_t MinSizeLimit = 0;

//! File is excluded if it is over this size
uint64_t MaxSizeLimit = std::numeric_limits<uint64_t>::max();
};

} // namespace pcktool
13 changes: 11 additions & 2 deletions src/PckTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ int PckTool::Run()

return 0;
} else if(Opts.Action == "add" || Opts.Action == "a") {
std::unique_ptr<PckFile> pck;

if(Files.empty()) {
std::cout << "ERROR: no files specified\n";
return 1;
}

std::unique_ptr<PckFile> pck;

if(TargetExists()) {
std::cout << "Target pck exists, loading it before adding new files\n";

Expand All @@ -88,6 +88,8 @@ int PckTool::Run()
} else {
pck = std::make_unique<PckFile>(Opts.Pack);

SetIncludeFilter(*pck);

pck->SetGodotVersion(Opts.GodotMajor, Opts.GodotMinor, Opts.GodotPatch);
}

Expand Down Expand Up @@ -140,6 +142,8 @@ std::unique_ptr<PckFile> PckTool::LoadPck()

auto pck = std::make_unique<PckFile>(Opts.Pack);

SetIncludeFilter(*pck);

if(!pck->Load()) {
std::cout << "ERROR: couldn't load pck file: " << pck->GetPath() << "\n";
return nullptr;
Expand All @@ -148,6 +152,11 @@ std::unique_ptr<PckFile> PckTool::LoadPck()
return pck;
}
// ------------------------------------ //
void PckTool::SetIncludeFilter(PckFile& pck)
{
pck.SetIncludeFilter(std::bind(&FileFilter::Include, Opts.Filter, std::placeholders::_1));
}
// ------------------------------------ //
bool PckTool::BuildFileList()
{
// Copy standard files
Expand Down
6 changes: 6 additions & 0 deletions src/PckTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "Define.h"

#include "FileFilter.h"

#include <nlohmann/json.hpp>

#include <memory>
Expand Down Expand Up @@ -35,6 +37,8 @@ class PckTool {
int GodotPatch;

json FileCommands;

FileFilter Filter;
};

public:
Expand All @@ -53,6 +57,8 @@ class PckTool {

std::unique_ptr<PckFile> LoadPck();

void SetIncludeFilter(PckFile& pck);

private:
Options Opts;

Expand Down
20 changes: 19 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Define.h"
#include "FileFilter.h"
#include "PckTool.h"

#include <cxxopts.hpp>
Expand Down Expand Up @@ -50,6 +51,10 @@ int main(int argc, char* argv[])
cxxopts::value<std::string>())
("set-godot-version", "Set the godot version to use when creating a new pck",
cxxopts::value<std::string>()->default_value("3.0.0"))
("min-size-filter", "Set minimum size for files to include in operation",
cxxopts::value<uint64_t>())
("max-size-filter", "Set maximum size for files to include in operation",
cxxopts::value<uint64_t>())
("v,version", "Print version and quit")
("h,help", "Print help and quit")
;
Expand Down Expand Up @@ -85,6 +90,7 @@ int main(int argc, char* argv[])
std::string removePrefix;
int godotMajor, godotMinor, godotPatch;
nlohmann::json fileCommands;
pcktool::FileFilter filter;

if(result.count("file")) {
files = result["file"].as<decltype(files)>();
Expand All @@ -102,6 +108,18 @@ int main(int argc, char* argv[])
pack = result["pack"].as<std::string>();
}

if(result.count("pack")) {
pack = result["pack"].as<std::string>();
}

if(result.count("min-size-filter")) {
filter.SetSizeMinLimit(result["min-size-filter"].as<uint64_t>());
}

if(result.count("max-size-filter")) {
filter.SetSizeMaxLimit(result["max-size-filter"].as<uint64_t>());
}

action = result["action"].as<std::string>();

try {
Expand Down Expand Up @@ -144,7 +162,7 @@ int main(int argc, char* argv[])
}

auto tool = pcktool::PckTool({pack, action, files, output, removePrefix, godotMajor,
godotMinor, godotPatch, fileCommands});
godotMinor, godotPatch, fileCommands, filter});

return tool.Run();
}
17 changes: 15 additions & 2 deletions src/pck/PckFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ bool PckFile::Load()
return ReadContainedFileContents(offset, size);
};

if(IncludeFilter && !IncludeFilter(entry))
continue;

Contents[entry.Path] = std::move(entry);
};

Expand Down Expand Up @@ -114,6 +117,7 @@ bool PckFile::Save()
Write32(0);
}

// Things are filtered before adding to Contents, so we don't do any filtering here
// File count
Write32(Contents.size());

Expand Down Expand Up @@ -148,6 +152,8 @@ bool PckFile::Save()
// Align
int alignment = 0;

// TODO: add command line flag to enable alignment

if(alignment >= 4) {
while(File->tellg() % alignment != 0) {
uint8_t null = 0;
Expand Down Expand Up @@ -200,6 +206,9 @@ bool PckFile::Save()
// ------------------------------------ //
void PckFile::AddFile(ContainedFile&& file)
{
if(IncludeFilter && !IncludeFilter(file))
return;

Contents[file.Path] = std::move(file);
}
// ------------------------------------ //
Expand Down Expand Up @@ -232,8 +241,6 @@ void PckFile::AddSingleFile(const std::string& filesystemPath, std::string pckPa
if(pckPath.empty())
throw std::runtime_error("path inside pck is empty to add file to");

std::cout << "Adding " << filesystemPath << " as " << pckPath << "\n";

ContainedFile file;

const auto size = std::filesystem::file_size(filesystemPath);
Expand Down Expand Up @@ -261,6 +268,12 @@ void PckFile::AddSingleFile(const std::string& filesystemPath, std::string pckPa
return data;
};

// TODO: might be nice to add an option to print out rejected files
if(IncludeFilter && !IncludeFilter(file))
return;

std::cout << "Adding " << filesystemPath << " as " << pckPath << "\n";

Contents[pckPath] = file;
}

Expand Down
11 changes: 11 additions & 0 deletions src/pck/PckFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ class PckFile {
PatchGodotVersion = patch;
}

//! \brief Sets a filter for entries to be added to this object
//!
//! This must be set before loading the data. The Save method doesn't apply the filter.
void SetIncludeFilter(std::function<bool(const ContainedFile&)> callback)
{
IncludeFilter = callback;
}

inline const auto& GetPath()
{
return Path;
Expand All @@ -96,6 +104,9 @@ class PckFile {
size_t PadPathsToMultipleWithNULLS = 4;

std::map<std::string, ContainedFile> Contents;

//! Used in a bunch of operations to check if a file entry should be included or ignored
std::function<bool(const ContainedFile&)> IncludeFilter;
};

} // namespace pcktool

0 comments on commit e9c07b1

Please sign in to comment.