This commit is contained in:
Martin Slachta
2026-07-18 14:31:15 +02:00
commit a04f0dc262
3343 changed files with 1140208 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
file(GLOB CXXFILES src/*.cpp)
add_library(loft_common OBJECT ${CXXFILES})
add_library(loft::common ALIAS loft_common)
target_include_directories(loft_common
PUBLIC
src/
)
+48
View File
@@ -0,0 +1,48 @@
#include <iostream>
#include "AdjacencyMatrix.hpp"
AdjacencyMatrixNodeHandle& AdjacencyMatrixNodeHandle::add_dependency(uint32_t on) {
m_graph->set(m_idx, on);
return *this;
}
std::vector<uint32_t> AdjacencyMatrixNodeHandle::dependencies() {
return m_graph->get_dependencies(m_idx);
}
bool AdjacencyMatrixNodeHandle::depends_on(uint32_t what) {
return m_graph->get(what, m_idx);
}
void AdjacencyMatrix::find_dft(uint32_t node, uint32_t target, uint32_t maxDepth) {
if(maxDepth == 0) {
throw std::runtime_error("Contains loop");
}
for(uint32_t x = 0; x < m_matrix.size(); x++) {
if(get(x, node)) {
unset(x, target);
find_dft(x, target, maxDepth - 1);
}
}
}
void AdjacencyMatrix::transitive_reduction() {
for(uint32_t x = 0; x < m_matrix.size(); x++) {
for(uint32_t y = 0; y < m_matrix.size(); y++) {
if(get(y, x)) {
find_dft(y, x, m_matrix.size());
}
}
}
}
void AdjacencyMatrix::print() {
for(uint32_t x = 0; x < m_matrix.size(); x++) {
for(uint32_t y = 0; y < m_matrix.size(); y++) {
std::cout << get(x, y) << " ";
}
std::cout << std::endl;
}
}
+189
View File
@@ -0,0 +1,189 @@
#pragma once
#include <cstdint>
#include <vector>
#include <map>
#include "Assert.h"
struct AdjacencyMatrix;
struct AdjacencyMatrixNodeHandle {
private:
AdjacencyMatrix* m_graph;
uint32_t m_idx;
public:
AdjacencyMatrixNodeHandle(
AdjacencyMatrix* graph,
uint32_t idx
) :
m_graph(graph),
m_idx(idx) {
}
AdjacencyMatrixNodeHandle& add_dependency(uint32_t on);
std::vector<uint32_t> dependencies();
bool depends_on(uint32_t what);
};
/**
* Represents a graph as an adjacency matrix.
*/
struct AdjacencyMatrix {
private:
std::vector<std::vector<bool>> m_matrix;
std::map<std::string, uint32_t> m_node_idx;
std::vector<std::string> m_node_names;
void find_dft(uint32_t node, uint32_t target, uint32_t maxDepth);
public:
explicit AdjacencyMatrix(std::vector<std::string> node_names) :
m_matrix(node_names.size(), std::vector<bool>(node_names.size())),
m_node_names(node_names)
{
for(uint32_t x = 0; x < node_names.size(); x++) {
m_node_idx.insert({node_names[x], x});
}
}
bool has_loop() {
return false;
}
const std::vector<std::vector<bool>>& rows () const {
return m_matrix;
}
const std::vector<bool>& row(const std::string& name) const {
ASSERT(m_node_idx.contains(name));
return m_matrix[m_node_idx.at(name)];
}
[[nodiscard]] [[deprecated("Use string variant")]] bool get(uint32_t from, uint32_t to) const {
ASSERT(from < m_matrix.size() && to < m_matrix.size());
return m_matrix[from][to];
}
[[nodiscard]] bool get(const std::string& from, const std::string& to) const {
ASSERT(m_node_idx.contains(from) && m_node_idx.contains(to));
return m_matrix[m_node_idx.at(from)][m_node_idx.at(to)];
}
inline AdjacencyMatrix& set(uint32_t from, uint32_t to) {
ASSERT(from < m_matrix.size() && to < m_matrix.size());
m_matrix[from][to] = true;
return *this;
}
inline AdjacencyMatrix& unset(uint32_t from, uint32_t to) {
ASSERT(from < m_matrix.size() && to < m_matrix.size());
m_matrix[from][to] = false;
return *this;
}
inline AdjacencyMatrix& set(const std::string& from, const std::string& to) {
ASSERT(m_node_idx.contains(from) && m_node_idx.contains(to));
m_matrix[m_node_idx.at(from)][m_node_idx.at(to)] = true;
return *this;
}
inline AdjacencyMatrix& unset(const std::string& from, const std::string& to) {
ASSERT(m_node_idx.contains(from) && m_node_idx.contains(to));
m_matrix[m_node_idx.at(from)][m_node_idx.at(to)] = false;
return *this;
}
/**
* Counts and returns number of dependencies of item at 'to' index
* @param to Index of the dependant
* @return number representing count of dependencies
*/
[[nodiscard]] uint32_t num_dependencies(uint32_t to) const {
ASSERT(to < m_matrix.size());
uint32_t numDependencies = 0;
for(uint32_t x = 0; x < m_matrix.size(); x++) {
if(x == to) continue;
if(get(x, to)) {
numDependencies++;
}
}
return numDependencies;
}
[[nodiscard]] uint32_t num_dependencies_of(const std::string& node) const {
return num_dependencies(m_node_idx.at(node));
}
/**
* Gets all the dependencies of 'to' item as vector
* @param to Index of the dependant
* @return vector of indices of dependencies
*/
[[nodiscard]] std::vector<uint32_t> get_dependencies(uint32_t to) const {
ASSERT(to < m_matrix.size());
uint32_t numDependencies = num_dependencies(to);
std::vector<uint32_t> dependencies(numDependencies);
uint32_t i = 0;
for(uint32_t x = 0; x < m_matrix.size() && i < numDependencies; x++) {
if(x == to) continue;
if(get(x, to)) {
dependencies[i++] = x;
}
}
return dependencies;
}
[[nodiscard]] std::vector<std::string> get_dependencies(const std::string& to) const {
uint32_t numDependencies = num_dependencies(m_node_idx.at(to));
std::vector<std::string> dependencies(numDependencies);
uint32_t i = 0;
for(uint32_t x = 0; x < m_matrix.size() && i < numDependencies; x++) {
if(get(m_node_names[x], to)) {
dependencies[i++] = m_node_names[x];
}
}
return dependencies;
}
[[nodiscard]] std::vector<std::string> get_successors(const std::string& from) const {
std::vector<std::string> successors;
uint32_t i = 0;
for(auto& node : m_node_names) {
if(get(from, node)) {
successors.push_back(node);
}
}
return successors;
}
/**
* Does a transitive reduction on the matrix.
*/
void transitive_reduction();
void print();
};
+14
View File
@@ -0,0 +1,14 @@
//
// Created by martin on 7/5/24.
//
#ifndef LOFT_ASSERT_H
#define LOFT_ASSERT_H
#include <stdexcept>
#include <format>
#include <source_location>
#define ASSERT(expr) if(!(expr)) { throw std::runtime_error(std::format("Assertion failed in {}: {}", std::source_location::current().function_name(), #expr)); }
#endif //LOFT_ASSERT_H
+15
View File
@@ -0,0 +1,15 @@
//
// Created by marti on 7/1/2024.
//
#ifndef LOFT_DISPLAY_H
#define LOFT_DISPLAY_H
namespace lft {
class Display {
public:
virtual void display() const = 0;
};
}
#endif //LOFT_DISPLAY_H
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
+34
View File
@@ -0,0 +1,34 @@
//
// Created by marti on 7/1/2024.
//
#ifndef LOFT_ERROR_H
#define LOFT_ERROR_H
#include <string>
#include <utility>
#include "Display.h"
namespace lft {
enum ErrorCode {
};
class Error : lft::Display {
private:
ErrorCode m_code;
std::string m_message;
public:
Error(const ErrorCode code, std::string message) :
m_code(code), m_message(std::move(message)) {
}
void display() const override {
}
};
}
#endif //LOFT_ERROR_H
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <vector>
#include <cstdint>
template<typename FromT, typename IntoT>
inline std::vector<IntoT> map(const std::vector<FromT>& original, std::unary_function<FromT, IntoT> func) {
std::vector<IntoT> result(original.size());
for(uint32_t i = 0; i < original; i++) {
result[i] = func(original[i]);
}
return result;
}
+66
View File
@@ -0,0 +1,66 @@
//
// Created by marti on 7/1/2024.
//
#ifndef LOFT_LOG_H
#define LOFT_LOG_H
#include <cstdarg>
#include <cstdio>
#define LOG_ENABLE 1
class Log {
private:
FILE *output;
public:
#if LOG_ENABLE
Log() {
output = stdout;
}
inline void fail(const char* format, ...) const {
va_list args;
va_start(args, format);
fwrite("[FAIL]: ", 1, 8, output);
vfprintf(output, format, args);
fwrite("\n", 1, 1, output);
}
inline void warn(const char* format, ...) const {
va_list args;
va_start(args, format);
vfprintf(output, format, args);
fwrite("\n", 1, 1, output);
}
inline void done(const char* format, ...) const {
va_list args;
va_start(args, format);
vfprintf(output, format, args);
fwrite("\n", 1, 1, output);
}
inline void mesg(const char* format, ...) const {
va_list args;
va_start(args, format);
vfprintf(output, format, args);
fwrite("\n", 1, 1, output);
}
#else
inline void fail(const char* format, ...) const {}
inline void warn(const char* format, ...) const {}
inline void done(const char* format, ...) const {}
inline void mesg(const char* format, ...) const {}
#endif
};
static Log log = Log();
#define FAIL(fmt, ...) log.fail(fmt, ##__VA_ARGS__)
#endif //LOFT_LOG_H
+41
View File
@@ -0,0 +1,41 @@
#pragma once
template<typename TValue, typename TError>
class result {
private:
bool m_isSuccess;
union {
TValue m_value;
TError m_error;
} m_value;
public:
result<TValue, TError>() : m_isSuccess(false) {
}
void set_ok(TValue value) {
m_value.m_value = value;
m_isSuccess = true;
}
void set_fail(TError err) {
m_value.m_error = err;
m_isSuccess = false;
}
};
template<typename TSuccess, typename TError>
result<TSuccess, TError> fail(TError failure) {
auto r = result<TSuccess, TError>();
r.set_fail(failure);
return r;
}
template<typename TSuccess, typename TError>
result<TSuccess, TError> ok(TSuccess value) {
auto r = result<TSuccess, TError>();
r.set_ok(value);
return r;
}