summaryrefslogtreecommitdiff
path: root/src/base/state.c
diff options
context:
space:
mode:
authordautor <karlo98.m@gmail.com>2024-11-16 13:22:54 +0100
committerdautor <karlo98.m@gmail.com>2024-11-16 17:54:38 +0100
commit47778ccd67cbb3fb70dda706911d3166038ca010 (patch)
tree906bf0537d14f5ce8e2528736fb89a3499ada214 /src/base/state.c
Import project
Diffstat (limited to 'src/base/state.c')
-rw-r--r--src/base/state.c380
1 files changed, 380 insertions, 0 deletions
diff --git a/src/base/state.c b/src/base/state.c
new file mode 100644
index 0000000..50ebe4e
--- /dev/null
+++ b/src/base/state.c
@@ -0,0 +1,380 @@
+#include "state.h"
+
+// FREE
+
+void
+Free_endpoint(endpoint *E)
+{
+ free(E->Address);
+ free(E->Hook);
+}
+
+void
+Free_endpoint_configuration(endpoint_configuration *E)
+{
+ free(E->Node);
+ free(E->Interface);
+}
+
+void
+Free_link_configuration(link_configuration *E)
+{
+ Free_endpoint_configuration(E->Peer + 0);
+ Free_endpoint_configuration(E->Peer + 1);
+}
+
+void
+Free_link(link_ *E)
+{
+ free(E->Name);
+ Free_link_configuration(&E->Configuration);
+ Free_endpoint(E->Peer + 0);
+ Free_endpoint(E->Peer + 1);
+}
+
+void
+Free_node_configuration(node_configuration *E)
+{
+ free(E->Module);
+ ucl_object_unref(E->Configuration);
+}
+
+void
+Free_node(node *E)
+{
+ free(E->Name);
+ Free_node_configuration(&E->Configuration);
+ ucl_object_unref(E->Data);
+}
+
+void
+Free_experiment(experiment *E)
+{
+ for(size_t i = 0; i < E->NodeCount; ++i) Free_node(E->Node + i);
+ free(E->Node);
+ for(size_t i = 0; i < E->LinkCount; ++i) Free_link(E->Link + i);
+ free(E->Link);
+}
+
+// PARSE
+
+char *
+Parse_endpoint(endpoint *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ if(root == NULL || root->type != UCL_OBJECT)
+ {
+ if(*Position == '\0') Position = ".";
+ asprintf(&Error, "%s is not an object", Position);
+ goto error;
+ }
+ ucl_object_t const *address = ucl_object_lookup(root, "address");
+ if(address == NULL || address->type != UCL_STRING)
+ {
+ asprintf(&Error, "%s.address is not a string", Position);
+ goto error;
+ }
+ ucl_object_t const *hook = ucl_object_lookup(root, "hook");
+ if(hook == NULL || hook->type != UCL_STRING)
+ {
+ asprintf(&Error, "%s.hook is not a string", Position);
+ goto error;
+ }
+ E->Address = strdup(ucl_object_tostring(address));
+ E->Hook = strdup(ucl_object_tostring(hook));
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_endpoint_configuration(endpoint_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *node = ucl_object_lookup(root, "node");
+ UCL_CHECK(node, STRING);
+ ucl_object_t const *interface = ucl_object_lookup(root, "interface");
+ UCL_CHECK(interface, STRING);
+ E->Node = strdup(ucl_object_tostring(node));
+ E->Interface = strdup(ucl_object_tostring(interface));
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_link_configuration(link_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ size_t EndpointAt = 0;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *peer0 = ucl_object_lookup(root, "peer0");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.peer0", Position);
+ Error = Parse_endpoint_configuration(&E->Peer[EndpointAt], peer0, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ ++EndpointAt;
+ }
+ ucl_object_t const *peer1 = ucl_object_lookup(root, "peer1");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.peer1", Position);
+ Error = Parse_endpoint_configuration(&E->Peer[EndpointAt], peer1, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ ++EndpointAt;
+ }
+ return NULL;
+error:
+ for(size_t i = 0; i < EndpointAt; ++i) Free_endpoint_configuration(E->Peer + i);
+ return Error;
+}
+
+char *
+Parse_link(link_ *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ size_t EndpointAt = 0;
+ bool Configuration = false;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *configuration = ucl_object_lookup(root, "configuration");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.configuration", Position);
+ Error = Parse_link_configuration(&E->Configuration, configuration, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ Configuration = true;
+ }
+ ucl_object_t const *peer0 = ucl_object_lookup(root, "peer0");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.peer0", Position);
+ Error = Parse_endpoint(E->Peer + EndpointAt, peer0, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ ++EndpointAt;
+ }
+ ucl_object_t const *peer1 = ucl_object_lookup(root, "peer1");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.peer1", Position);
+ Error = Parse_endpoint(E->Peer + EndpointAt, peer1, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ ++EndpointAt;
+ }
+ return NULL;
+error:
+ for(size_t i = 0; i < EndpointAt; ++i) Free_endpoint(E->Peer + i);
+ if(Configuration == true) Free_link_configuration(&E->Configuration);
+ return Error;
+}
+
+char *
+Parse_node_configuration(node_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *module = ucl_object_lookup(root, "module");
+ UCL_CHECK(module, STRING);
+ ucl_object_t const *configuration = ucl_object_lookup(root, "configuration");
+ if(configuration == NULL)
+ {
+ asprintf(&Error, "%s.configuration does not exist", Position);
+ goto error;
+ }
+ E->Module = strdup(ucl_object_tostring(module));
+ E->Configuration = ucl_object_copy(configuration);
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_node(node *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ bool Configuration = false;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *configuration = ucl_object_lookup(root, "configuration");
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.configuration", Position);
+ Error = Parse_node_configuration(&E->Configuration, configuration, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ Configuration = true;
+ }
+ ucl_object_t const *data = ucl_object_lookup(root, "data");
+ if(data == NULL)
+ {
+ asprintf(&Error, "%s.does not exist", Position);
+ goto error;
+ }
+ E->Data = ucl_object_copy(data);
+ return NULL;
+error:
+ if(Configuration == true) Free_node_configuration(&E->Configuration);
+ return Error;
+}
+
+char *
+Parse_experiment(experiment *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ size_t NodeAt = 0;
+ size_t LinkAt = 0;
+ if(root == NULL) return NULL;
+ UCL_CHECK_ROOT(OBJECT);
+ {
+ ucl_object_t const *nodes = ucl_object_lookup(root, "nodes");
+ UCL_CHECK(nodes, OBJECT);
+ E->NodeCount = nodes->len;
+ E->Node = calloc(sizeof(node), E->NodeCount);
+ ucl_object_t const *v;
+ ucl_object_iter_t it = NULL;
+ while((v = ucl_iterate_object(nodes, &it, true)))
+ {
+ char const *k = ucl_object_key(v);
+ if(k == NULL) continue;
+ node *I = E->Node + NodeAt;
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.nodes['%s']", Position, k);
+ Error = Parse_node(I, v, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ I->Name = strdup(k);
+ NodeAt++;
+ }
+ }
+ {
+ ucl_object_t const *links = ucl_object_lookup(root, "links");
+ UCL_CHECK(links, OBJECT);
+ E->LinkCount = links->len;
+ E->Link = calloc(sizeof(link_), E->LinkCount);
+ ucl_object_t const *v;
+ ucl_object_iter_t it = NULL;
+ while((v = ucl_iterate_object(links, &it, true)))
+ {
+ char const *k = ucl_object_key(v);
+ if(k == NULL) continue;
+ link_ *I = E->Link + LinkAt;
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.links['%s']", Position, k);
+ Error = Parse_link(I, v, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ I->Name = strdup(k);
+ LinkAt++;
+ }
+ }
+ return NULL;
+error:
+ E->NodeCount = NodeAt;
+ E->LinkCount = LinkAt;
+ Free_experiment(E);
+ return Error;
+}
+
+// SAVE
+
+void
+Save_endpoint(jprint_state *S, endpoint const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "address");
+ JPrint_string(S, E->Address);
+ JPrintMember(S, "hook");
+ JPrint_string(S, E->Hook);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_endpoint_configuration(jprint_state *S, endpoint_configuration const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "node");
+ JPrint_string(S, E->Node);
+ JPrintMember(S, "interface");
+ JPrint_string(S, E->Interface);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_link_configuration(jprint_state *S, link_configuration const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "peer0");
+ Save_endpoint_configuration(S, E->Peer + 0);
+ JPrintMember(S, "peer1");
+ Save_endpoint_configuration(S, E->Peer + 1);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_link(jprint_state *S, link_ const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "configuration");
+ Save_link_configuration(S, &E->Configuration);
+ JPrintMember(S, "peer0");
+ Save_endpoint(S, E->Peer + 0);
+ JPrintMember(S, "peer1");
+ Save_endpoint(S, E->Peer + 1);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_node_configuration(jprint_state *S, node_configuration const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "module");
+ JPrint_string(S, E->Module);
+ JPrintMember(S, "configuration");
+ JPrint_ucl_object_t(S, E->Configuration);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_node(jprint_state *S, node const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "configuration");
+ Save_node_configuration(S, &E->Configuration);
+ JPrintMember(S, "data");
+ JPrint_ucl_object_t(S, E->Data);
+ JPrintObjectEnd(S);
+}
+
+void
+Save_experiment(jprint_state *S, experiment const *E)
+{
+ JPrintObjectBegin(S);
+ {
+ JPrintMember(S, "nodes");
+ JPrintObjectBegin(S);
+ for(size_t i = 0; i < E->NodeCount; ++i)
+ {
+ node *I = E->Node + i;
+ JPrintMember(S, I->Name);
+ Save_node(S, I);
+ }
+ JPrintObjectEnd(S);
+ }
+ {
+ JPrintMember(S, "links");
+ JPrintObjectBegin(S);
+ for(size_t i = 0; i < E->LinkCount; ++i)
+ {
+ link_ *I = E->Link + i;
+ JPrintMember(S, I->Name);
+ Save_link(S, E->Link + i);
+ }
+ JPrintObjectEnd(S);
+ }
+ JPrintObjectEnd(S);
+}