Program Listing for File types.cc#
↰ Return to documentation for file (src/types.cc)
#include <charconv>
#include <cstring>
#include "nodes-graph/types.h"
namespace ng {
const char* as_string(Status status) {
switch (status) {
case Status::Ok: return "Ok";
case Status::NoOutputSocket: return "NoOutputSocket";
case Status::NoInputSocket: return "NoInputSocket";
case Status::IncompatibleTypes: return "IncompatibleTypes";
case Status::NotLinkable: return "NotLinkable";
case Status::CausesCycle: return "CausesCycle";
case Status::InvalidValue: return "InvalidValue";
case Status::NotAllowedValue: return "NotAllowedValue";
case Status::DuplicateAlias: return "DuplicateAlias";
case Status::NoWritableHead: return "NoWritableHead";
case Status::UnknownHead: return "UnknownHead";
case Status::NoQualifier: return "NoQualifier";
case Status::IncompleteQualifier: return "IncompleteQualifier";
case Status::IOError: return "IOError";
}
return "Unknown";
}
// ---
node_id_t as_node_id(const char* str, std::size_t unique) {
if (unique > MAX_NODE_RANDOM_ID)
throw std::out_of_range("Unique ID exceeds maximum allowed value");
if (unique == 0)
throw std::out_of_range("Unique ID must be greater than zero");
node_id_t id = as_node_id(str);
std::size_t start = 0;
while (id[start] != 0) { start++; }
// '#' + at most (LEN_MAX_NODE_RANDOM_ID - 1) digits + '\0'
std::array<char, LEN_MAX_NODE_RANDOM_ID + 1> buffer{0};
buffer[0] = '#';
std::to_chars(
buffer.data() + 1,
buffer.data() + buffer.size() - 1,
unique
);
std::size_t len = 0;
while (buffer[len] != 0) { ++len; }
std::size_t excess = (start + len) > (NODE_ID_SIZE - 1) ? (start + len) - (NODE_ID_SIZE - 1) : 0;
start -= excess;
std::memcpy(
id.data() + start,
buffer.data(),
len
);
return id;
}
node_id_t as_node_id(const qualifier_t& q, std::size_t unique) {
return as_node_id(
q.chunks[qualifier_t::N_CHUNKS-1].data(),
unique
);
}
// ---
socket_uuid_t as_socket_uuid(const node_id_t& node, const socket_id_t& socket) {
return std::make_pair(node, socket);
}
socket_uuid_t as_socket_uuid(const node_id_t& node, const char* str_socket) {
return std::make_pair(node, as_socket_id(str_socket));
}
link_t as_link(const socket_uuid_t& from, const socket_uuid_t& to) {
return std::make_pair(to, from);
}
// ---
qualifier_t::qualifier_t(std::initializer_list<const char*> init) {
std::size_t i = 0;
for (const char* str : init) {
if (i >= N_CHUNKS) {
throw std::out_of_range("Too many chunks in initializer list");
}
chunks[i] = as_qchunk(str);
++i;
}
while (i < N_CHUNKS) {
chunks[i] = null_qchunk;
++i;
}
}
qualifier_t::qualifier_t(std::initializer_list<qchunk_t> init) {
std::size_t i = 0;
for (const qchunk_t& chunk : init) {
if (i >= N_CHUNKS) {
throw std::out_of_range("Too many chunks in initializer list");
}
chunks[i] = chunk;
++i;
}
while (i < N_CHUNKS) {
chunks[i] = null_qchunk;
++i;
}
}
bool qualifier_t::is_complete() const {
for (std::size_t i = 0; i < N_CHUNKS; ++i) {
if (eq_qchunk(chunks[i], null_qchunk)) {
return false;
}
}
return true;
}
bool cmp_qualifier(const qualifier_t& a, const qualifier_t& b) {
for (std::size_t i = 0; i < qualifier_t::N_CHUNKS; ++i) {
if (cmp_qchunk(a.chunks[i], b.chunks[i])) {
return true;
} else if (cmp_qchunk(b.chunks[i], a.chunks[i])) {
return false;
}
}
return false;
}
bool eq_qualifier(const qualifier_t& a, const qualifier_t& b) {
for (std::size_t i = 0; i < qualifier_t::N_CHUNKS; ++i) {
if (!eq_qchunk(a.chunks[i], b.chunks[i])) {
return false;
}
}
return true;
}
std::filesystem::path as_filepath(const qualifier_t& q) {
std::filesystem::path path = "";
for (std::size_t i = 0; i < qualifier_t::N_CHUNKS; ++i) {
path /= std::string(q.chunks[i].data());
}
path += ".graph";
return path;
}
std::string as_string(const qualifier_t& q) {
std::string result;
for (std::size_t i = 0; i < qualifier_t::N_CHUNKS; ++i) {
if (i > 0) { result += SPLIT_CHAR; }
result += q.chunks[i].data();
}
return result;
}
qualifier_t as_qualifier(const char* c_str) {
std::string str = c_str;
std::size_t start = 0, next = 0, rank = 0;
std::string s;
qualifier_t qualifier;
if (str.empty())
return qualifier;
while (true) {
next = str.find(SPLIT_CHAR, start);
s = str.substr(start, next - start);
start = next + 1;
if (s.empty())
throw std::runtime_error("Empty chunk in qualifier");
qualifier.chunks[rank++] = as_qchunk(s.c_str());
if (next == std::string::npos || rank >= qualifier_t::N_CHUNKS) break;
}
if (rank < qualifier_t::N_CHUNKS)
throw std::runtime_error("Not enough chunks in qualifier");
if (next != std::string::npos)
throw std::runtime_error("Too many chunks in qualifier");
return qualifier;
}
} // namespace ng