#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); }