initial
This commit is contained in:
+8
@@ -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/
|
||||
)
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
+34
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user