API Reference#

This page mixes hand-written text with documentation extracted directly from the source code comments via Breathe – this is exactly the mechanism we want to illustrate here.

The graph#

Graph is the central class: it owns the nodes, the sockets, and the links that connect them together.

class Graph#

Public Functions

inline Graph &set_name(const std::string &n)#
inline const std::string &get_name() const#
inline const std::map<ng::socket_uuid_t, InputSocket> &get_input_sockets() const#
inline const std::map<ng::socket_uuid_t, OutputSocket> &get_output_sockets() const#
inline const std::map<ng::node_id_t, Node> &get_nodes() const#
inline const std::set<ng::link_t> &get_links() const#
ng::node_id_t add_node(const ng::qualifier_t &node_qualifier)#
Node &get_node(const ng::node_id_t &node_id)#
void remove_node(const ng::node_id_t &node_id)#
void disconnect_node(const ng::node_id_t &node_id)#
void rename_node(const ng::node_id_t &q, const std::string &n)#
int set_socket_value(const ng::socket_uuid_t sid, const std::string &val)#
int add_link(const ng::socket_uuid_t &from, const ng::socket_uuid_t &to)#
Graph() = default#
Graph(const std::string &n)#

Nodes#

A Node represents an instance of a computation task within a graph. Its identifier is generated automatically at creation time (see make_node_random_id).

class Node#

Public Functions

void set_name(const std::string &n)#
inline const std::string &get_name() const#
inline const ng::node_id_t &get_id() const#
inline const ng::qualifier_t &get_qualifier() const#
Node()#
Node(const std::string &name)#
Node(const std::string &name, const ng::node_id_t &id, const ng::qualifier_t &qualifier)#

Public Static Functions

static size_t make_node_random_id()#

Sockets#

Socket is the base class shared by InputSocket and OutputSocket. Important reminder for anyone reading this code: an input socket can only take part in a single link at a time, unlike an output socket.

class Socket#

Subclassed by InputSocket, OutputSocket

Public Functions

Socket &set_socket_type(ng::socket_t t)#
inline const std::string &get_name() const#
inline const ng::socket_id_t &get_id() const#
inline ng::socket_t get_socket_type() const#
inline bool is_active() const#
Socket(const std::string &name = "", const ng::socket_id_t &id = ng::null_socket, const ng::socket_t &type = ng::null_socket_type)#

Friends

friend class Graph
class InputSocket : public Socket#

Public Functions

Socket &set_value(const std::string &val)#
Socket &set_validator(bool (*v)())#
Socket &set_allowed_values(const std::vector<std::string> &v)#
Socket &set_linkable(bool l)#
inline const std::string &get_value() const#
inline const std::vector<std::string> &get_allowed_values() const#
inline bool is_linkable() const#
void register_on_value_changed_callback(ng::value_callback_t cb)#
InputSocket(const std::string &name = "", const ng::socket_id_t &id = ng::null_socket, const ng::socket_t &type = ng::null_socket_type, const std::string &value = "", bool (*validator)() = nullptr, bool linkable = true)#

Public Members

bool(*)() get_validator () const

Friends

friend class Graph
class OutputSocket : public Socket#

Public Functions

OutputSocket(const std::string &name = "", const ng::socket_id_t &id = ng::null_socket, const ng::socket_t &type = ng::null_socket_type)#

Friends

friend class Graph

Node definitions and registry#

Each concrete node type (for example ImageCalculator) registers itself into NodesRegistry at program startup, through the self-registration pattern NodeDefinitionRegistrar – see src/node_definitions/image_calculator_node.cc for a concrete example of this mechanism.

class NodeDefinition#

Public Functions

NodeDefinition() = default#
NodeDefinition(const ng::qualifier_t &node_type_id, const std::vector<InputSocket> &input_sockets, const std::vector<OutputSocket> &output_sockets, const std::string &default_name)#
const ng::qualifier_t &get_node_type_id() const#
const std::vector<InputSocket> &get_input_sockets() const#
const std::vector<OutputSocket> &get_output_sockets() const#
const std::string &get_default_name() const#
class NodesRegistry#

Public Functions

NodesRegistry() = default#
NodesRegistry(const NodesRegistry&) = delete#
NodesRegistry &operator=(const NodesRegistry&) = delete#
void register_definition(const ng::qualifier_t &type, NodeDefinition definition)#
const NodeDefinition &get(const ng::qualifier_t &type) const#
inline const std::map<ng::qualifier_t, NodeDefinition> &get_definitions() const#
inline size_t size() const#

Public Static Functions

static NodesRegistry &instance()#

Constraints#

Constraints validate the value of an input socket before it is accepted by the graph.

class Constraint#

Subclassed by ConstraintEnum

Public Functions

virtual ~Constraint() = default#
virtual bool is_applicable(const InputSocket &s) const = 0#
virtual bool is_respected(const InputSocket &s, const std::string &val) const = 0#
class ConstraintsManager#

Public Functions

ConstraintsManager(const ConstraintsManager&) = delete#
ConstraintsManager &operator=(const ConstraintsManager&) = delete#
ConstraintsManager(ConstraintsManager&&) = delete#
ConstraintsManager &operator=(ConstraintsManager&&) = delete#
int check_constraints(const InputSocket &s, const std::string &val) const#
inline size_t size() const#

Public Static Functions

static inline ConstraintsManager &instance()#

Core types (ng namespace)#

The ng namespace groups together all the low-level identification types used throughout the project – qualifiers, node/socket identifiers, links, etc.

namespace ng#

Typedefs

using value_callback_t = void (*)(Graph &g, InputSocket &to, const std::string &old_value)#
using socket_t = uint32_t#

The type(s) supposed to be represented within this socket. 0 is supposed to be reserved as an equivalent of None/null.

using socket_id_t = std::array<char, SOCKET_ID_SIZE>#
using node_id_t = std::array<char, NODE_ID_SIZE>#
using socket_uuid_t = std::pair<node_id_t, socket_id_t>#

Compile-time checks to ensure that socket_id_t and node_id_t are distinct types. This is important to prevent accidental misuse of these types in the codebase. A socket UUID (Unique Universal Identifier) is a pair consisting of a node ID and a socket ID. All the sockets have the same ID within all the instances of a same node type.

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 qchunk_t = std::array<char, QUALIFIER_CHUNK_SIZE>#

Functions

constexpr size_t pow(size_t base, size_t exp)#
socket_id_t as_socket_id(const char *str)#
bool cmp_socket_id(const socket_id_t &a, const socket_id_t &b)#
bool operator<(const socket_id_t &a, const socket_id_t &b)#
bool cmp_node_id(const node_id_t &a, const node_id_t &b)#
bool operator<(const node_id_t &a, const node_id_t &b)#
socket_uuid_t as_socket_uuid(const node_id_t &node, const socket_id_t &socket)#
link_t as_link(const socket_uuid_t &to, const socket_uuid_t &from)#
qchunk_t as_qchunk(const char *c)#
bool cmp_qchunk(const qchunk_t &a, const qchunk_t &b)#
bool operator<(const qchunk_t &a, const qchunk_t &b)#
bool cmp_qualifier(const qualifier_t &a, const qualifier_t &b)#
bool operator<(const qualifier_t &a, const qualifier_t &b)#
qualifier_t as_qualifier(const char *str)#
node_id_t as_node_id(const char *str)#
node_id_t as_node_id(const char *str, size_t unique)#
node_id_t as_node_id(const qualifier_t &q, size_t unique)#

Variables

constexpr socket_t null_socket_type = 0#
constexpr socket_t all_socket_type = ~0#
constexpr size_t SOCKET_ID_SIZE = 24#

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. The size of the socket ID is defined by SOCKET_ID_SIZE.

constexpr socket_id_t null_socket = {0}#
constexpr socket_id_t inf_socket = {~0}#
constexpr size_t NODE_ID_SIZE = 32#

A node 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. The size of the node ID is defined by NODE_ID_SIZE. The node IDs will be built from the top level of the node type and a random index. For example, for the node of type “ab.cd:ef”, the node ID could be “ef#6454” where 6454 is a random index.

constexpr node_id_t null_node = {0}#
constexpr size_t LEN_MAX_NODE_RANDOM_ID = 7#
constexpr size_t MAX_NODE_RANDOM_ID = pow(10, LEN_MAX_NODE_RANDOM_ID - 1) - 1#
constexpr std::size_t QUALIFIER_CHUNK_SIZE = 28#

Qualifiers allow to identify a ressource through a hierarchy of chunks from the most global to the most specific. Each chunk is a fixed-size array of characters, and the number of chunks is defined by n_chunks. An exemple of qualifier could be “cv4mic.image_manip:image_calculator”

constexpr char SPLIT_CHAR = '.'#
struct qualifier_t#
#include <types.h>

Public Functions

qualifier_t()#
qualifier_t(std::initializer_list<qchunk_t> init)#
qualifier_t(std::initializer_list<const char*> init)#

Public Members

qchunk_t chunks[N_CHUNKS]#

Public Static Attributes

static constexpr std::size_t N_CHUNKS = 3#