Core types#

enum class ng::Status : int

Result of the operations that can fail without it being exceptional (adding a link, setting a value, saving a graph, …).

Values:

enumerator Ok
enumerator NoOutputSocket
enumerator NoInputSocket
enumerator IncompatibleTypes
enumerator NotLinkable
enumerator CausesCycle
enumerator InvalidValue
enumerator NotAllowedValue
enumerator DuplicateAlias
enumerator NoWritableHead
enumerator UnknownHead
enumerator NoQualifier
enumerator IncompleteQualifier
enumerator IOError
enum class ng::LinkBreakReason

Values:

enumerator Manual
enumerator Replaced
enumerator NodeRemoved
enumerator Other

Signature of callback functions executed when a new link between two sockets is successfully added.

Signature of callback functions executed when an existing link between two sockets is broken. The breaking reason can be specified using the LinkBreakReason enum.

using ng::value_changed_callback_t = void (*)(Graph &g, Node &node, InputSocket &socket, const std::string &old_value)

Whenever an action involving a value change in an input socket is executed, a corresponding callback function is going to be called. The signature on the given callback function should match value_changed_callback_t. Keep in mind that socket values are represented by std::string.

using ng::validator_t = bool (*)(const std::string &value)

Signature of validator functions used to validate socket values. All the values are represented by strings when stored in sockets.

using ng::socket_t = uint32_t

Indicate the different types that a socket can represent. 0 is supposed to be reserved as an equivalent of None/null. Each type is represented by a bit (bit mask) and a socket with several possible types can be represented by combining several types using the bitwise operator ‘|’. The null_socket_type represents a socket with no type assigned. The all_socket_type represents a socket that can accept all types.

using ng::qchunk_t = std::array<char, QUALIFIER_CHUNK_SIZE>

qchunk_t represents a fixed-size array of characters used as a chunk in a qualifier_t.

using ng::socket_id_t = std::array<char, SOCKET_ID_SIZE>

A socket is represented by a unique identifier, which is a fixed-size array of characters. The null ID is represented by an array full of 0s (null_socket). The infinite ID is represented by an array full of CHAR_MAX (inf_socket). The size of the socket ID is defined by SOCKET_ID_SIZE.

using ng::node_id_t = std::array<char, NODE_ID_SIZE>

A node is identified in a graph by a unique fixed-size array of characters. It is composed of:

  • A node type identifier (the last chunk of the node’s type qualifier).

  • A random index to ensure uniqueness within the node type. Both these elements are split with a ‘#’. Note that if the name is too long to fit the index, it will be truncated. The null ID is represented by an array full of 0s (null_node). The size of the node ID is defined by NODE_ID_SIZE. For example, for the node of type “ab.cd.ef”, the node ID could be “ef#6454” where 6454 is a random index. The last character will always be ‘\0’.

using ng::socket_uuid_t = std::pair<node_id_t, socket_id_t>

A socket UUID (Unique Universal IDentifier) is a pair consisting of a node ID and a socket ID. It allows to identify a socket within a graph uniquely. All the sockets have the same ID within all the instances of a same node type, hence the need for a UUID. It is composed of:

  • The node ID of the node to which the socket belongs.

  • The socket ID within that node.

A link is a pair (to, from) of socket UUIDs, representing a connection from one socket to another. The fact that “to” is first allows to detect if a given input socket is already linked faster because the list will be sorted by “to”. Since an input socket can only have one connection, it is the priority to be able to check that.

using ng::graph_id_t = uint16_t
using ng::data_id_t = std::size_t

0 is reserved and means “no data”.

template<typename DB>
using ng::operator_instantiator_t = Operator<DB> *(*)(const std::string &name)
using ng::NodesRegistry = Registry<qualifier_t, NodeDefinition>
using ng::ValidatorsRegistry = Registry<socket_t, validator_t>
using ng::ValueChangedCallbacksRegistry = Registry<qualifier_t, value_changed_callback_t>
using ng::LinkAddedCallbacksRegistry = Registry<qualifier_t, link_added_callback_t>
using ng::LinkBrokenCallbacksRegistry = Registry<qualifier_t, link_broken_callback_t>
template<typename DB>
using ng::OperatorInstantiatorsRegistry = Registry<qualifier_t, operator_instantiator_t<DB>>
constexpr socket_t ng::null_socket_type = 0

See socket_t for more details on the representation of socket types.

constexpr socket_t ng::all_socket_type = ~socket_t{0}

See socket_t for more details on the representation of socket types.

constexpr std::size_t ng::QUALIFIER_CHUNK_SIZE = 28
constexpr qchunk_t ng::null_qchunk = {0}
constexpr char ng::SPLIT_CHAR = '.'
constexpr std::size_t ng::SOCKET_ID_SIZE = 24
constexpr socket_id_t ng::null_socket = {0}

See socket_id_t for more details on the representation of socket IDs.

constexpr socket_id_t ng::inf_socket = detail::filled_array<SOCKET_ID_SIZE>(CHAR_MAX)

See socket_id_t for more details on the representation of socket IDs.

constexpr std::size_t ng::NODE_ID_SIZE = 32
constexpr node_id_t ng::null_node = {0}

See node_id_t for more details on the representation of node IDs.

constexpr std::size_t ng::LEN_MAX_NODE_RANDOM_ID = 7

Maximum number of characters of the random suffix, including the ‘#’.

constexpr std::size_t ng::MAX_NODE_RANDOM_ID = detail::pow(10, LEN_MAX_NODE_RANDOM_ID - 1) - 1
constexpr data_id_t ng::null_data = 0
template<typename T>
std::optional<T> ng::parse_from_string(const std::string &str)
std::vector<node_id_t> ng::sorted_by_depth(const Graph &graph)
Throws:

std::runtime_error – if the graph contains a cycle.

Returns:

The nodes of the graph sorted by increasing depth.

template<typename Key, typename Value, typename Compare = std::less<Key>>
SmallMap<Key, Value, Compare> ng::make_from_set(const std::set<Key, Compare> &s, const Value &default_value)

Builds a SmallMap whose keys are the content of s, all mapped to default_value.

inline bool ng::operator<(const Socket &a, const Socket &b)
const char *ng::as_string(Status status)
constexpr qchunk_t ng::as_qchunk(const char *c)
inline bool ng::cmp_qchunk(const qchunk_t &a, const qchunk_t &b)
inline bool ng::eq_qchunk(const qchunk_t &a, const qchunk_t &b)
bool ng::cmp_qualifier(const qualifier_t &a, const qualifier_t &b)
bool ng::eq_qualifier(const qualifier_t &a, const qualifier_t &b)
inline bool ng::operator<(const qualifier_t &a, const qualifier_t &b)
inline bool ng::operator==(const qualifier_t &a, const qualifier_t &b)
inline bool ng::operator!=(const qualifier_t &a, const qualifier_t &b)
constexpr qualifier_t ng::null_qualifier(null_qchunk, null_qchunk, null_qchunk)
constexpr qualifier_t ng::make_qualifier(const char *a, const char *b, const char *c)

Compile-time alternative to as_qualifier, without any validation.

qualifier_t ng::as_qualifier(const char *str)

Constructs a qualifier_t from a given C-style string (“abc.def.ghi”). An empty string produces the null qualifier.

Throws:

std::runtime_error – if the string doesn’t contain exactly N_CHUNKS non-empty chunks.

std::filesystem::path ng::as_filepath(const qualifier_t &q)

Converts a qualifier_t to a piece of filepath that can be joined with a root to form an absolute filepath.

std::string ng::as_string(const qualifier_t &q)

Converts a qualifier_t to its dotted representation (“abc.def.ghi”).

constexpr socket_id_t ng::as_socket_id(const char *str)

Converts a C-style string to a socket ID. The input will be truncated if necessary to reach the size defined by SOCKET_ID_SIZE. The last character will always be ‘\0’. If the string is shorter, the resulting ID will be padded with 0s.

inline bool ng::cmp_socket_id(const socket_id_t &a, const socket_id_t &b)
inline bool ng::ends_with(const socket_id_t &arr, const char *suffix)
constexpr node_id_t ng::as_node_id(const char *str)
node_id_t ng::as_node_id(const char *str, std::size_t unique)
Throws:

std::out_of_range – if unique is 0 or greater than MAX_NODE_RANDOM_ID.

node_id_t ng::as_node_id(const qualifier_t &q, std::size_t unique)
Throws:

std::out_of_range – if unique is 0 or greater than MAX_NODE_RANDOM_ID.

inline bool ng::cmp_node_id(const node_id_t &a, const node_id_t &b)
inline bool ng::ends_with(const node_id_t &arr, const char *suffix)
socket_uuid_t ng::as_socket_uuid(const node_id_t &node, const socket_id_t &socket)

Constructs a socket UUID from a given node ID and socket ID.

socket_uuid_t ng::as_socket_uuid(const node_id_t &node, const char *str_socket)
link_t ng::as_link(const socket_uuid_t &from, const socket_uuid_t &to)

Constructs a link from the given “from” and “to” socket UUIDs. Beware that the resulting pair is stored as (to, from).

struct CmpGraph#
#include <graph.h>

Deep comparison of two graphs: every node, socket, link and interface is compared by value.

Public Functions

bool equal(const Graph &a, const Graph &b) const#
bool same_node(const Node &a, const Node &b) const#
bool same_socket(const Socket &a, const Socket &b) const#
bool same_input_socket(const InputSocket &a, const InputSocket &b) const#
bool same_output_socket(const OutputSocket &a, const OutputSocket &b) const#
bool same_interface(const Graph::InterfaceProperties &a, const Graph::InterfaceProperties &b) const#
template<typename ...Ts>
class DataBank#
#include <data_bank.h>

Storage of the data exchanged by operators at runtime. There is one pool per type, all the pools share the same IDs sequence so an ID identifies a single item. The ID 0 (null_data) is never attributed.

Public Functions

template<typename T>
inline std::map<data_id_t, T> &get_pool()#
template<typename T>
inline const std::map<data_id_t, T> &get_pool() const#
template<typename T>
inline data_id_t add(const T &value)#
Returns:

The ID of the new item.

template<typename T>
inline std::optional<T> get(data_id_t id) const#
inline bool contains(data_id_t id) const#
Returns:

true if any pool contains this ID.

inline void erase(data_id_t id)#
inline data_id_t reserve_id()#

Reserves an ID that can later be filled with store.

inline data_id_t get_next_id() const#
template<typename ...Args>
inline bool load(data_id_t id, std::variant<Args...> &var) const#

Fills var with the item id, using the first alternative of the variant having an item with this ID.

Returns:

false if none of the alternatives has an item with this ID.

template<typename ...Args>
inline bool store(data_id_t id, const std::variant<Args...> &var)#

Stores the content of var under id, replacing any previous item with this ID, whatever its type.

Returns:

false if there is no pool for the type held by the variant.

inline data_id_t add_from_string(const std::string &str)#

Parses the string with the Parser of each type, in the order of the template parameters, and adds the first successful result.

Returns:

The ID of the new item, or null_data if no parser accepted the string.

Public Static Attributes

template<typename T>
static constexpr bool has_pool = (std::is_same_v<T, Ts> || ...)#
class Graph#
#include <graph.h>

Public Types

using input_sockets_t = std::map<socket_uuid_t, InputSocket>#
using output_sockets_t = std::map<socket_uuid_t, OutputSocket>#
using nodes_t = std::map<node_id_t, Node>#
using interface_t = std::map<socket_uuid_t, InterfaceProperties>#

Public Functions

inline void set_name(const std::string &name)#
inline void set_qualifier(const qualifier_t &q)#
inline const std::string &get_name() const#
inline const std::optional<qualifier_t> &get_qualifier() const#
inline const input_sockets_t &get_input_sockets() const#
inline const output_sockets_t &get_output_sockets() const#
inline const nodes_t &get_nodes() const#
inline const links_t &get_links() const#
inline const interface_t &get_parameters() const#
inline const interface_t &get_results() const#
node_id_t add_node(const qualifier_t &node_qualifier)#
Returns:

The ID of the new node, or null_node if the node type is not registered.

node_id_t add_node(const char *node_qualifier)#
inline bool has_node(const node_id_t &node_id) const#
Node &get_node(const node_id_t &node_id)#
Throws:

std::out_of_range – if the node doesn’t exist.

const Node &get_node(const node_id_t &node_id) const#
bool remove_node(const node_id_t &node_id)#

Removes the node, its links, its sockets and their exposure in the interface.

Returns:

false if the node doesn’t exist.

void disconnect_node(const node_id_t &node_id, LinkBreakReason reason = LinkBreakReason::Manual)#

Breaks all the links going to or coming from the node.

void rename_node(const node_id_t &node_id, const std::string &name)#
Throws:

std::out_of_range – if the node doesn’t exist.

const InputSocket &get_input_socket(const socket_uuid_t &suuid) const#
Throws:

std::out_of_range – if the socket doesn’t exist.

const OutputSocket &get_output_socket(const socket_uuid_t &suuid) const#
Status set_socket_value(const socket_uuid_t &suuid, const std::string &value)#

Sets the value of an input socket, after checking the validators and the allowed values. The callbacks of the socket are triggered only if the value is accepted.

const std::string &get_socket_value(const socket_uuid_t &suuid) const#
Throws:

std::out_of_range – if the input socket doesn’t exist.

Status add_link(const socket_uuid_t &from, const socket_uuid_t &to)#

Links an output socket to an input socket. If the input socket is already linked, the previous link is replaced. If the input socket is exposed as a parameter, it stops being exposed. Adding a link that already exists is a no-op returning Status::Ok.

Returns:

false if the link doesn’t exist.

Returns:

An iterator to the link targeting this input socket, or get_links().end().

inline bool is_linked(const socket_uuid_t &input) const#
links_t get_input_links(const node_id_t &node_id) const#
Returns:

All the links whose destination is a socket of this node.

links_t get_output_links(const node_id_t &node_id) const#
Returns:

All the links whose source is a socket of this node.

Status expose_parameter(const socket_uuid_t &suuid, const socket_id_t &alias, std::string show_as = "")#

Exposes an input socket as a parameter of the graph, so it becomes an input of the proxy nodes. Any link targeting this socket is broken.

Parameters:
  • suuid – The socket to expose.

  • alias – The ID of the socket on the proxy nodes, must be unique among parameters.

  • show_as – The name of the socket on the proxy nodes. Defaults to the socket’s name.

bool remove_parameter(const socket_uuid_t &suuid)#
Status expose_result(const socket_uuid_t &suuid, const socket_id_t &alias, std::string show_as = "")#

Same as expose_parameter, for output sockets.

bool remove_result(const socket_uuid_t &suuid)#
node_id_t add_proxy_node(const qualifier_t &graph_qualifier)#

Adds a node representing another graph, loaded from the disk through the GraphManager. Its inputs are the parameters of that graph and its outputs are its results.

Throws:

std::runtime_error – if the graph can’t be found.

Returns:

The ID of the new node, or null_node if the graph tries to contain itself.

node_id_t add_proxy_node(const char *graph_qualifier)#
std::set<node_id_t> get_source_nodes() const#
Returns:

The nodes that are not the destination of any link.

DepthProperties get_depth_properties() const#
struct DepthProperties#
#include <graph.h>

Public Members

SmallMap<node_id_t, std::size_t> depth#

Length of the longest path from a source node to each node. Only meaningful for nodes that are not in (or downstream of) a cycle.

std::size_t max_depth = 0#

Largest value in depth.

bool has_cycle = false#

Whether the links form at least one cycle.

struct InterfaceProperties#
#include <graph.h>

How a socket is exposed in the interface (parameters or results) of a graph.

Public Members

std::string show_as#

Name displayed for the socket of the proxy node.

socket_id_t socket_id#

ID of the socket of the proxy node.

class GraphManager#
#include <graph_manager.h>

Owns the graphs in memory and the “heads”: root folders on the disk where graphs are saved. A graph with the qualifier “a.b.c” is saved in “<head>/a/b/c.graph”.

Public Types

enum class Owner#

Ordered from the most personal to the least personal: when saving, the most personal writable head is used.

Values:

enumerator User#
enumerator Group#
enumerator Global#
enumerator Unknown#
using head_id_t = std::size_t#
using library_t = std::map<qualifier_t, head_id_t>#
using heads_t = SmallMap<head_id_t, HeadProperties>#

Public Functions

GraphManager(const GraphManager&) = delete#
GraphManager &operator=(const GraphManager&) = delete#
~GraphManager() = default#
inline const library_t &get_library() const#
inline const heads_t &get_heads() const#
inline const Graph &get_graph(graph_id_t id) const#
Throws:

std::out_of_range – if the graph doesn’t exist.

inline Graph &get_graph(graph_id_t id)#
inline bool has_graph(graph_id_t id) const#
graph_id_t new_graph(const std::string &name = "")#
bool close_graph(graph_id_t id)#
Returns:

false if the graph doesn’t exist.

head_id_t add_head(const std::filesystem::path &path, Owner owner = Owner::User)#

Registers a new head and discovers the graphs it contains.

void refresh()#

Re-discovers the graphs contained in all the readable heads.

bool exists(const qualifier_t &q) const#
Returns:

true if a graph with this qualifier exists in one of the heads.

Status save_graph(graph_id_t id)#

Saves the graph in the most personal writable head.

Status save_graph(graph_id_t id, head_id_t head_id)#
Graph raw_read(const qualifier_t &q) const#

Reads a graph from the disk without registering it in the manager.

Throws:

std::runtime_error – if the graph can’t be found or read.

graph_id_t load_graph(const qualifier_t &q, bool force = false)#

Loads a graph from the disk and registers it in the manager. If it was already loaded and force is false, the ID of the graph in memory is returned.

Throws:

std::runtime_error – if the graph can’t be found or read.

void reset()#

Forgets everything: graphs in memory and heads. Mostly useful for tests.

Public Static Functions

static bool can_write(const std::filesystem::path &path)#
static bool can_read(const std::filesystem::path &path)#
static GraphManager &instance()#
struct HeadProperties#
#include <graph_manager.h>

Public Functions

inline HeadProperties(Owner owner = Owner::Unknown, const std::filesystem::path &path = "", bool readable = false, bool writable = false)#

Public Members

Owner owner#
std::filesystem::path path#
bool readable#
bool writable#
template<typename DB>
class GraphRuntime#
#include <graph_runtime.h>

Converts a graph into a flat sequence of operators, sorted by depth, and runs them. Proxy nodes are expanded recursively: their operators are inlined at their position. Unlinked inputs are parsed from the value of their socket.

Public Types

using operator_t = Operator<DB>#
using operator_ptr_t = std::unique_ptr<operator_t>#
using bindings_t = std::map<socket_id_t, data_id_t>#

Public Functions

explicit GraphRuntime(const Graph &graph)#
Throws:

std::runtime_error – if an operator is missing, a proxy can’t be read or the graph contains a cycle.

explicit GraphRuntime(graph_id_t gid)#

Builds the runtime of a graph owned by the GraphManager.

inline const std::vector<operator_ptr_t> &get_operators() const#
inline const DB &get_data_bank() const#
inline DB &get_data_bank()#
inline const bindings_t &get_results() const#
inline bool is_executed(std::size_t index) const#
template<typename T>
inline std::optional<T> get_result(const socket_id_t &alias) const#
Returns:

The value of a result of the graph, if it has been computed with this type.

template<typename T>
inline std::optional<T> get_result(const char *alias) const#
bool run()#

Runs all the operators in order. Stops at the first operator failing to pull, poll, process or push.

Returns:

true if all the operators were executed.

class InputSocket : public ng::Socket#
#include <socket.h>

Public Functions

InputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::string &value = "", bool linkable = true, const std::set<std::string> &allowed_values = {}, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {}, const std::set<qualifier_t> &on_value_changed_callbacks = {})#
bool set_value(const std::string &value)#

Sets the value if it is allowed (see is_allowed_value). Validators are not checked here (see check_validity).

Returns:

true if the value was accepted.

inline void set_allowed_values(const std::set<std::string> &values)#
inline void set_linkable(bool linkable)#
inline const std::string &get_value() const#
inline const std::set<std::string> &get_allowed_values() const#
inline bool is_linkable() const#
inline bool is_enum() const#
inline const std::set<qualifier_t> &get_on_value_changed_callbacks() const#
inline void register_on_value_changed_callback(const qualifier_t &cb)#
bool is_allowed_value(const std::string &value) const#

A value is allowed if the socket has no whitelist, or if the value is in the whitelist.

bool check_validity(const std::string &value) const#

Checks the value against the validators registered (ValidatorsRegistry) for the types of this socket. The value is valid if no validator is registered for any of the socket’s types, or if at least one of the registered validators accepts it.

void trigger_on_value_changed_callbacks(Graph &graph, Node &node, const std::string &old_value)#
class Node#
#include <node.h>

Instance of a node in a graph. The node only knows the IDs of its sockets, the sockets themselves are owned by the Graph.

Public Functions

Node(const std::string &name = "", const node_id_t &id = null_node, const qualifier_t &qualifier = null_qualifier, const std::set<socket_id_t> &input_sockets = {}, const std::set<socket_id_t> &output_sockets = {}, bool proxy = false)#
inline void set_name(const std::string &name)#
inline void set_proxy(bool proxy)#
inline const std::string &get_name() const#
inline const node_id_t &get_id() const#
inline const qualifier_t &get_qualifier() const#
inline const std::set<socket_id_t> &get_input_sockets() const#
inline const std::set<socket_id_t> &get_output_sockets() const#
inline bool is_proxy() const#
inline std::size_t n_input_sockets() const#
inline std::size_t n_output_sockets() const#
inline bool has_input_socket(const socket_id_t &socket_id) const#
inline bool has_output_socket(const socket_id_t &socket_id) const#
bool register_input_socket(const socket_id_t &socket_id)#
Returns:

true if the socket was not already registered.

bool register_output_socket(const socket_id_t &socket_id)#
bool remove_input_socket(const socket_id_t &socket_id)#
Returns:

true if the socket was registered.

bool remove_output_socket(const socket_id_t &socket_id)#

Public Static Functions

static std::size_t make_random_id()#
Returns:

A random number in [1, MAX_NODE_RANDOM_ID].

static void seed_random_ids(uint32_t seed)#

Re-seeds the random IDs generator, to make the generated node IDs reproducible.

class NodeDefinition#
#include <node_definition.h>

Blueprint of a node type, registered in the NodesRegistry under its qualifier. Graph::add_node copies its sockets into the graph to create a new Node instance.

Public Functions

NodeDefinition() = default#
NodeDefinition(const qualifier_t &qualifier, const std::set<InputSocket> &input_sockets, const std::set<OutputSocket> &output_sockets, const std::string &default_name)#
inline const qualifier_t &get_qualifier() const#
inline const std::set<InputSocket> &get_input_sockets() const#
inline const std::set<OutputSocket> &get_output_sockets() const#
inline const std::string &get_default_name() const#
template<typename DB>
class Operator#
#include <operator.h>

Runtime counterpart of a node: the object actually doing the computation. Each socket of the node is bound to an item of the data bank. The runtime calls, in this order: pull (read inputs), poll (ready?), process (compute), push (write outputs).

Public Types

using bindings_t = std::map<socket_id_t, data_id_t>#

Public Functions

inline Operator(const std::string &name = "")#
inline Operator(const bindings_t &bindings, const std::string &name = "")#
virtual ~Operator() = default#
inline const std::string &get_name() const#
inline const bindings_t &get_bindings() const#
inline data_id_t get_binding(const socket_id_t &socket) const#
Returns:

The data ID bound to the socket, or null_data.

inline data_id_t get_binding(const char *socket) const#
inline void bind(const socket_id_t &socket, data_id_t id)#
virtual bool pull(const DB &db) = 0#
virtual bool poll() = 0#
virtual bool push(DB &db) = 0#
inline bool process()#
class OutputSocket : public ng::Socket#
#include <socket.h>

Public Functions

OutputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {})#
template<typename T>
struct Parser#

Converts the string value of a socket to a T. Must be specialized by the user of the library for each type stored in a DataBank: template <> struct ng::Parser<T> { static std::optional<T> parse(const std::string& str); };

struct qualifier_t#
#include <types.h>

Represents a hierarchical qualifier composed of multiple qchunk_t chunks. The order is opposite from a web URL, we go from most general to most specific. Ex: nodes_graph.structural.results_interface

Public Functions

qualifier_t(std::initializer_list<qchunk_t> init)#
qualifier_t(std::initializer_list<const char*> init)#
inline constexpr qualifier_t(const qchunk_t &a = null_qchunk, const qchunk_t &b = null_qchunk, const qchunk_t &c = null_qchunk)#
inline qchunk_t &operator[](std::size_t index)#
inline const qchunk_t &operator[](std::size_t index) const#
bool is_complete() const#

Public Members

qchunk_t chunks[N_CHUNKS]#

Public Static Attributes

static constexpr std::size_t N_CHUNKS = 3#
template<typename Key, typename Value>
class Registry#
#include <registry.h>

Global key -> value store, used for self-registration at static-initialization time. There is exactly one instance per (Key, Value) pair, reachable through instance(). An entry can never be overwritten: registering an existing key is a no-op.

Public Types

using map_type = std::map<Key, Value>#
using iterator = typename map_type::iterator#
using const_iterator = typename map_type::const_iterator#

Public Functions

Registry() = default#
Registry(const Registry&) = delete#
Registry &operator=(const Registry&) = delete#
inline bool register_entry(Key key, Value value)#
Returns:

true if the entry was inserted, false if the key already existed.

inline bool register_entries(std::vector<std::pair<Key, Value>> list)#
Returns:

true if all the entries were inserted.

inline const Value &get(const Key &key) const#
Throws:

std::out_of_range – if the key is not registered.

inline Value get_safe(const Key &key, Value default_value) const#
inline bool contains(const Key &key) const#
inline std::size_t size() const#
inline const map_type &get_all() const#
inline iterator find(const Key &key)#
inline const_iterator find(const Key &key) const#
inline iterator begin()#
inline const_iterator begin() const#
inline iterator end()#
inline const_iterator end() const#

Public Static Functions

static inline Registry<Key, Value> &instance()#
template<typename Key, typename Value, typename Compare = std::less<Key>>
class SmallMap#
#include <small_map.h>

Sorted associative container backed by a contiguous std::vector. Cheaper than std::map for small sizes and cache-friendly to iterate. Insertion and erasure are O(n), lookup is O(log n).

Public Types

using key_type = Key#
using mapped_type = Value#
using value_type = std::pair<Key, Value>#
using key_compare = Compare#
using container_type = std::vector<value_type>#
using iterator = typename container_type::iterator#
using const_iterator = typename container_type::const_iterator#
using size_type = typename container_type::size_type#

Public Functions

SmallMap() = default#
inline explicit SmallMap(Compare comp)#
inline SmallMap(std::initializer_list<value_type> init, Compare comp = Compare())#
inline iterator begin() noexcept#
inline iterator end() noexcept#
inline const_iterator begin() const noexcept#
inline const_iterator end() const noexcept#
inline const_iterator cbegin() const noexcept#
inline const_iterator cend() const noexcept#
inline bool empty() const noexcept#
inline size_type size() const noexcept#
inline void reserve(size_type n)#
inline size_type capacity() const noexcept#
inline void clear() noexcept#
inline iterator find(const Key &key)#
inline const_iterator find(const Key &key) const#
inline bool contains(const Key &key) const#
inline size_type count(const Key &key) const#
inline Value &at(const Key &key)#
inline const Value &at(const Key &key) const#
inline Value &operator[](const Key &key)#
inline Value &operator[](Key &&key)#
inline std::pair<iterator, bool> insert(const value_type &kv)#
inline std::pair<iterator, bool> insert(value_type &&kv)#
template<typename ...Args>
inline std::pair<iterator, bool> emplace(Args&&... args)#
template<typename V>
inline std::pair<iterator, bool> insert_or_assign(const Key &key, V &&value)#
inline iterator erase(iterator pos)#
inline iterator erase(const_iterator pos)#
inline size_type erase(const Key &key)#
inline container_type &data() noexcept#
inline const container_type &data() const noexcept#
inline key_compare key_comp() const#
class Socket#
#include <socket.h>

Attributes shared by input and output sockets. Sockets are value types: they are copied from their NodeDefinition into the Graph when a node is instantiated.

Subclassed by ng::InputSocket, ng::OutputSocket

Public Functions

inline void set_name(const std::string &name)#
inline void set_type(socket_t type)#
inline void set_active(bool active)#
inline void set_alias(const std::string &name, const socket_id_t &id)#

Used by proxies to re-expose a socket under another name and ID.

inline const std::string &get_name() const#
inline const socket_id_t &get_id() const#
inline socket_t get_type() const#
inline bool is_active() const#
inline bool accepts_type(socket_t type) const#