Skip to content

Commit

Permalink
feature: loading the library as a metalib using the psl::serializer u…
Browse files Browse the repository at this point in the history
…nifying the behaviour (#132)

* feature: loading the library as a metalib unifying the behaviour
* fixed and tested behaviour of new library
* fixed clang-format not doing a left merge correctly
* fix for the windows yml test runner (see: actions/runner-images#10004 )
  • Loading branch information
JessyDL authored Jun 10, 2024
1 parent cce6207 commit 4c705e5
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 59 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ jobs:
- name: initialize
run: |
python3 tools/generate_project_info.py
cmake --preset=windows-${{ matrix.bitconfig }}-release-${{ matrix.graphics }} -DPE_BENCHMARKS=${{ matrix.benchmarks }}
# todo: DCMAKE_CXX_FLAGS here is a workaround for an issue in the CI runner, which should be rechecked in a couple of weeks or so.
# see https://github.com/actions/runner-images/issues/10004
cmake --preset=windows-${{ matrix.bitconfig }}-release-${{ matrix.graphics }} -DPE_BENCHMARKS=${{ matrix.benchmarks }} -DCMAKE_CXX_FLAGS="/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR"
python3 tools/patch.py --project ./project_files/${{ matrix.arch }}/
- name: compile
run: cmake --build --preset=windows-${{ matrix.bitconfig }}-release-${{ matrix.graphics }} -j ${{ steps.cpu-cores.outputs.count }}
Expand Down
33 changes: 33 additions & 0 deletions psl/inc/psl/library.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,39 @@ class file {
static const uint64_t polymorphic_identity;
};

class metalib {
public:
struct entry {
struct file {
static constexpr psl::string8::view serialization_name {"FILE"};
template <typename S>
void serialize(S& s) {
s << path << time;
}
psl::serialization::property<"PATH", psl::string8_t> path;
psl::serialization::property<"TIME", std::uint64_t> time;
};
template <typename S>
void serialize(S& s) {
s << id << data << meta << environments;
}

static constexpr psl::string8::view serialization_name {"ENTRY"};
psl::serialization::property<"UID", psl::UID> id;
psl::serialization::property<"DATA", file> data;
psl::serialization::property<"META", file> meta;
psl::serialization::property<"ENV", std::vector<psl::string8_t>> environments;
};

template <typename S>
void serialize(S& s) {
s << entries;
}

static constexpr psl::string8::view serialization_name {"METALIB"};
psl::serialization::property<"ENTRIES", std::vector<entry>> entries;
};

/// \brief container class for meta::file's
///
/// a meta::library is a collection of meta::file instances. The library will do the basic bookkeeping, allowing you
Expand Down
85 changes: 28 additions & 57 deletions psl/src/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ const uint64_t file::polymorphic_identity {register_polymorphic<file>()};
library::library() {}

library::library(std::optional<psl::string8::view> lib, std::vector<psl::string8_t> environment) {
auto library = [&lib]() {
if(lib) {
// it makes no sense to specify a path if the file is not there, this must be a mistake or error.
psl_assert(
psl::utility::platform::file::exists(psl::from_string8_t(*lib)), "Could not find library at '{}'", *lib);
return psl::utility::platform::file::read(psl::from_string8_t(*lib)).value_or("");
}
return psl::string8_t();
}();
m_LibraryLocation = psl::utility::platform::directory::to_platform(lib.value_or(""));
auto loc = m_LibraryLocation.rfind(psl::to_string8_t(psl::utility::platform::directory::seperator));
m_LibraryFolder = psl::string8::view(&m_LibraryLocation[0], loc);
Expand All @@ -35,68 +26,48 @@ library::library(std::optional<psl::string8::view> lib, std::vector<psl::string8
"could not find library at '{}'",
m_LibraryLocation);

if(!lib) {
return;
}

// Load library into memory
serializer s;

auto lines = [](const auto& file) {
std::vector<psl::string8_t> lines {};
lines.reserve(std::count(file.begin(), file.end(), '\n'));
auto index = file.find('\n');
size_t offset = 0;
while(index != psl::string8_t::npos) {
lines.emplace_back(file.substr(offset, index));
offset = index + 1;
index = file.find('\n', offset);
}
return lines;
}(library);

for(auto line : lines) {
size_t start = line.find("UID=") + 4;
size_t end = line.find("]", start);
psl::string8_t meta = line.substr(start, end - start);
auto uid = utility::converter<UID>::from_string(meta);
size_t startFilePath = line.find("PATH=") + 5;
size_t endFilePath = line.find("]", startFilePath);
size_t startPath = line.find("METAPATH=", endFilePath) + 9;
size_t endPath = line.find("]", startPath);

size_t startEnv = line.find("[ENV=");
size_t endEnv = line.find("]", startEnv);

if(startEnv != psl::string8_t::npos &&
std::find_if(std::begin(environment),
std::end(environment),
[env = psl::utility::string::split(line.substr(startEnv + 5, endEnv - (startEnv + 5)), ";")](
const psl::string8_t& expected) {
return std::find(std::begin(env), std::end(env), expected) != std::end(env);
}) == std::end(environment)) {
metalib metalib;
s.deserialize<decode_from_format>(metalib, lib.value());

for(auto& entry : metalib.entries.value) {
// here we handle environment variations
// if the environments for the file aren't empty we check if any_of the environments are also in the provided
// environment list, if not (or if the environment list is empty) we skip this entry
if(!entry.environments->empty() &&
!std::any_of(std::begin(environment), std::end(environment), [&entry](auto const& environment) {
return std::find(entry.environments->begin(), entry.environments->end(), environment) !=
entry.environments->end();
})) {
continue;
}
psl_assert(m_MetaData.find(uid) == std::end(m_MetaData), "duplicate UID {} found in library", uid.to_string());

psl::string8_t metapath = line.substr(startPath, endPath - startPath);
psl::string8_t filepath = line.substr(startFilePath, endFilePath - startFilePath);
psl::string8_t extension = filepath.substr(filepath.find_last_of('.') + 1);
psl_assert(m_MetaData.find(entry.id) == std::end(m_MetaData),
"duplicate UID {} found in library",
entry.id->to_string());

file* metaPtr = nullptr;
auto full_metapath = psl::utility::platform::file::to_platform(root + metapath);
auto full_metapath = psl::utility::platform::file::to_platform(root + entry.meta->path);
psl_assert(psl::utility::platform::file::exists(full_metapath),
"could not find file associated with UID {} at {}",
uid.to_string(),
full_metapath);
entry.id->to_string(),
entry.meta->path.value);

file* metaPtr = nullptr;
s.deserialize<decode_from_format>(metaPtr, full_metapath);

psl_assert(metaPtr->ID() == uid,
psl_assert(metaPtr->ID() == entry.id,
"UID mismatch between library and metafile library expected {} but file has {}",
uid.to_string(),
entry.id->to_string(),
metaPtr->ID().to_string());


auto pair = m_MetaData.emplace(metaPtr->ID(), std::move(metaPtr));
m_TagMap[filepath].insert(pair.first->second.data->ID());
m_TagMap[entry.data->path].insert(pair.first->second.data->ID());
pair.first->second.flags[0] = true;
pair.first->second.readableName = filepath;
pair.first->second.readableName = entry.data->path;
}
}

Expand Down
3 changes: 3 additions & 0 deletions psl/src/platform_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ psl::string psl::utility::platform::directory::sanitize(psl::string_view path) {
std::vector<psl::string> psl::utility::platform::directory::all_files(psl::string_view target_directory,
bool recursive) {
auto folder = to_platform(target_directory);
if(!exists(folder)) {
return {};
}
std::vector<psl::string> names;
if(recursive) {
for(std::filesystem::recursive_directory_iterator i(folder), end; i != end; ++i) {
Expand Down
15 changes: 14 additions & 1 deletion tools/clang-format.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@


def load_config(file: str = CONFIG_FILE):
# https://stackoverflow.com/a/24837438
def merge(dict1: dict, dict2: dict):
"""Recursively merges dict2 into dict1"""
if not isinstance(dict1, dict) or not isinstance(dict2, dict):
return dict2
for k in dict2:
if k in dict1:
dict1[k] = merge(dict1[k], dict2[k])
else:
dict1[k] = dict2[k]
return dict1

res = {
"formatting": {
"run-on-wsl": False,
Expand All @@ -28,7 +40,8 @@ def load_config(file: str = CONFIG_FILE):
}
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
res = res | json.load(f)
res = merge(res, json.load(f))

if isinstance(res["formatting"]["clang-format"], str):
res["formatting"]["clang-format"] = [res["formatting"]["clang-format"]]
return res
Expand Down

0 comments on commit 4c705e5

Please sign in to comment.