CyberiadaML-GraphML 1.0 read/write support according to the CyberiadaML-GraphML Primer document

This commit is contained in:
Alexey Fedoseev
2024-04-08 17:36:34 +03:00
parent ef4c304e5e
commit 61b5be4cd8
6 changed files with 2217 additions and 914 deletions

View File

@@ -8,15 +8,17 @@ else
endif
TEST_TARGET := cyberiada_test
LIB_SOURCES := cyberiadaml.c utf8enc.c
LIB_SOURCES := cyberiadaml.c utf8enc.c cyb_types.c
TEST_SOURCES := test.c
LIB_OBJECTS := $(patsubst %.c, %.o, $(LIB_SOURCES))
TEST_OBJECTS := $(patsubst %.c, %.o, $(TEST_SOURCES))
ifeq ($(DEBUG), 1)
CFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wconversion -fPIC -g3 -D__DEBUG__
CFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wconversion -fsanitize=address -fPIC -g3 -D__DEBUG_
LFLAGS := -fsanitize=address -static-libasan
else
CFLAGS := -fPIC
LFLAGS :=
endif
INCLUDE := -I. -I/usr/include/libxml2
@@ -31,7 +33,7 @@ else
endif
$(TEST_TARGET): $(TEST_OBJECTS) $(LIB_TARGET) $(LIB_ORJECTS)
gcc $(TEST_OBJECTS) -Wl,--no-as-needed $(LIBS) $(TEST_LIBS) -o $@
gcc $(TEST_OBJECTS) $(LFLAGS) -Wl,--no-as-needed $(LIBS) $(TEST_LIBS) -o $@
%.o: %.c
gcc -c $< $(CFLAGS) $(INCLUDE) -o $@

136
cyb_types.c Normal file
View File

@@ -0,0 +1,136 @@
/* -----------------------------------------------------------------------------
* The Cyberiada GraphML library implemention
*
* The basic data structures
*
* Copyright (C) 2024 Alexey Fedoseev <aleksey@fedoseev.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/
*
* ----------------------------------------------------------------------------- */
#include <string.h>
#include <stdlib.h>
#include "cyb_types.h"
int cyberiada_stack_push(CyberiadaStack** stack)
{
CyberiadaStack* new_item = (CyberiadaStack*)malloc(sizeof(CyberiadaStack));
memset(new_item, 0, sizeof(CyberiadaStack));
new_item->next = (*stack);
*stack = new_item;
return 0;
}
int cyberiada_stack_update_top_key(CyberiadaStack** stack, const char* new_key)
{
if (!stack || !*stack) {
return -1;
}
(*stack)->key = new_key;
return 0;
}
int cyberiada_stack_update_top_data(CyberiadaStack** stack, void* new_data)
{
if (!stack || !*stack) {
return -1;
}
(*stack)->data = new_data;
return 0;
}
void* cyberiada_stack_get_top_data(CyberiadaStack** stack)
{
CyberiadaStack* s;
if (!stack || !*stack) {
return NULL;
}
s = *stack;
while (s) {
if (s->data)
return s->data;
s = s->next;
}
return NULL;
}
int cyberiada_stack_pop(CyberiadaStack** stack)
{
CyberiadaStack* to_pop;
if (!stack || !*stack) {
return -1;
}
to_pop = *stack;
*stack = to_pop->next;
free(to_pop);
return 0;
}
int cyberiada_stack_is_empty(CyberiadaStack** stack)
{
return !stack || !*stack;
}
int cyberiada_stack_free(CyberiadaStack** stack)
{
while (!cyberiada_stack_is_empty(stack)) {
cyberiada_stack_pop(stack);
}
return 0;
}
int cyberiada_list_add(CyberiadaList** list, const char* key, void* data)
{
CyberiadaList* new_item;
if (!list) {
return -1;
}
new_item = (CyberiadaList*)malloc(sizeof(CyberiadaList));
new_item->key = key;
new_item->data = data;
new_item->next = *list;
*list = new_item;
return 0;
}
void* cyberiada_list_find(CyberiadaList** list, const char* key)
{
CyberiadaList* item;
if (!list || !*list) {
return NULL;
}
item = *list;
while (item) {
if (item->key && strcmp(item->key, key) == 0) {
return item->data;
}
item = item->next;
}
return NULL;
}
int cyberiada_list_free(CyberiadaList** list)
{
CyberiadaList* item;
if (!list) {
return 0;
}
while(*list) {
item = *list;
*list = item->next;
free(item);
}
return 0;
}

60
cyb_types.h Normal file
View File

@@ -0,0 +1,60 @@
/* -----------------------------------------------------------------------------
* The Cyberiada GraphML library implemention
*
* The basic data structures
*
* Copyright (C) 2024 Alexey Fedoseev <aleksey@fedoseev.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/
*
* ----------------------------------------------------------------------------- */
#ifndef __CYBERIADA_TYPES_H
#define __CYBERIADA_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
/* -----------------------------------------------------------------------------
* The Cyberiada GraphML basic data structures: stack and list
* ----------------------------------------------------------------------------- */
struct _CyberiadaStruct {
const char* key;
void* data;
struct _CyberiadaStruct* next;
};
typedef struct _CyberiadaStruct CyberiadaStack;
int cyberiada_stack_push(CyberiadaStack** stack);
int cyberiada_stack_update_top_key(CyberiadaStack** stack, const char* new_key);
int cyberiada_stack_update_top_data(CyberiadaStack** stack, void* new_data);
void* cyberiada_stack_get_top_data(CyberiadaStack** stack);
int cyberiada_stack_pop(CyberiadaStack** stack);
int cyberiada_stack_is_empty(CyberiadaStack** stack);
int cyberiada_stack_free(CyberiadaStack** stack);
typedef struct _CyberiadaStruct CyberiadaList;
int cyberiada_list_add(CyberiadaList** list, const char* key, void* data);
void* cyberiada_list_find(CyberiadaList** list, const char* key);
int cyberiada_list_free(CyberiadaList** list);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -38,15 +38,22 @@ typedef enum {
cybNodeCompositeState = 2, /* composite state */
cybNodeSubmachineState = 4, /* submachine state */
cybNodeComment = 8, /* comment node */
cybNodeMachineComment = 16, /* machine-readable comment node */
cybNodeFormalComment = 16, /* machine-readable comment node */
cybNodeInitial = 32, /* initial pseudostate */
cybNodeFinal = 64, /* final state */
cybNodeChoice = 128, /* choice pseudostate */
cybNodeTerminate = 256, /* terminate pseudostate */
cybNodeEntryPoint = 512, /* entry point pseudostate */
cybNodeExitPoint = 1024, /* exit point pseudostate */
cybNodeShallowHistory = 2048, /* shallow history pseudostate */
cybNodeDeepHistory = 4096, /* deep history pseudostate */
cybNodeFork = 8192, /* fork pseudostate */
cybNodeJoin = 16384, /* join pseudostate */
} CyberiadaNodeType;
typedef unsigned int CyberiadaNodeTypeMask;
/* SM node types: */
/* SM node types: */
typedef enum {
cybEdgeTransition = 0,
cybEdgeComment = 1,
@@ -57,7 +64,7 @@ typedef enum {
cybActionTransition = 0,
cybActionEntry = 1,
cybActionExit = 2,
cybActionDo = 4,
cybActionDo = 4
} CyberiadaActionType;
/* SM node & transitions geometry */
@@ -86,7 +93,21 @@ typedef struct _CyberiadaAction {
size_t behavior_len;
struct _CyberiadaAction* next;
} CyberiadaAction;
/* SM comment content */
typedef struct _CyberiadaCommentData {
char* body;
size_t body_len;
char* markup;
size_t markup_len;
} CyberiadaCommentData;
/* SM link (e.g. to a SM definition) */
typedef struct _CyberiadaLink {
char* ref;
size_t ref_len;
} CyberiadaLink;
/* SM node (state) */
typedef struct _CyberiadaNode {
CyberiadaNodeType type;
@@ -94,80 +115,101 @@ typedef struct _CyberiadaNode {
size_t id_len;
char* title;
size_t title_len;
CyberiadaAction* actions;
CyberiadaRect* geometry_rect;
struct _CyberiadaNode* next;
struct _CyberiadaNode* parent;
struct _CyberiadaNode* children;
} CyberiadaNode;
/* SM edge (transition) */
typedef struct _CyberiadaEdge {
CyberiadaEdgeType type;
char* id;
size_t id_len;
char* source_id;
size_t source_id_len;
char* target_id;
size_t target_id_len;
CyberiadaNode* source;
CyberiadaNode* target;
CyberiadaAction* action;
CyberiadaPoint* geometry_source_point;
CyberiadaPoint* geometry_target_point;
CyberiadaPolyline* geometry_polyline;
CyberiadaPoint* geometry_label;
CyberiadaAction* actions; /* for simple & composite nodes */
CyberiadaCommentData* comment_data; /* for comments */
CyberiadaLink* link; /* for submachine states */
CyberiadaPoint* geometry_point; /* for some pseudostates & final state */
CyberiadaRect* geometry_rect; /* for sm, states, and choice pseudostate */
char* color;
size_t color_len;
struct _CyberiadaEdge* next;
struct _CyberiadaNode* parent;
struct _CyberiadaNode* children;
struct _CyberiadaNode* next;
} CyberiadaNode;
typedef enum {
cybCommentSubjectNode = 0,
cybCommentSubjectNameFragment = 1,
cybCommentSubjectDataFragment = 2,
} CyberiadaCommentSubjectType;
typedef struct _CyberiadaCommentSubject {
CyberiadaCommentSubjectType type;
char* fragment;
size_t fragment_len;
} CyberiadaCommentSubject;
/* SM edge (transition) */
typedef struct _CyberiadaEdge {
CyberiadaEdgeType type;
char* id;
size_t id_len;
char* source_id;
size_t source_id_len;
char* target_id;
size_t target_id_len;
CyberiadaNode* source;
CyberiadaNode* target;
CyberiadaAction* action; /* for transition */
CyberiadaCommentSubject* comment_subject; /* for comment subject */
CyberiadaPolyline* geometry_polyline;
CyberiadaPoint* geometry_source_point;
CyberiadaPoint* geometry_target_point;
CyberiadaPoint* geometry_label_point;
char* color;
size_t color_len;
struct _CyberiadaEdge* next;
} CyberiadaEdge;
/* SM graph (state machine) */
typedef struct _CyberiadaSM {
CyberiadaNode* nodes;
CyberiadaEdge* edges;
struct _CyberiadaSM* next;
CyberiadaNode* nodes;
CyberiadaEdge* edges;
struct _CyberiadaSM* next;
} CyberiadaSM;
/* SM metainformation */
typedef struct {
/* HSM standard version (required parameter) */
char* standard_version;
size_t standard_version_len;
char* standard_version;
size_t standard_version_len;
/* target platform name */
char* platform_name;
size_t platform_name_len;
char* platform_name;
size_t platform_name_len;
/* target platform version */
char* platform_version;
size_t platform_version_len;
char* platform_version;
size_t platform_version_len;
/* target platform language */
char* platform_language;
size_t platform_language_len;
char* platform_language;
size_t platform_language_len;
/* target system controlled by the SM */
char* target_system;
size_t target_system_len;
char* target_system;
size_t target_system_len;
/* document name */
char* name;
size_t name_len;
char* name;
size_t name_len;
/* document author */
char* author;
size_t author_len;
char* author;
size_t author_len;
/* document author's contact */
char* contact;
size_t contact_len;
char* contact;
size_t contact_len;
/* document description */
char* description;
size_t description_len;
char* description;
size_t description_len;
/* document version */
char* version;
size_t version_len;
char* version;
size_t version_len;
/* document date */
char* date;
size_t date_len;
/* actions order flag (0 = not set, 1 = transition first, 2 = exit first) */
char actions_order_flag;
char* date;
size_t date_len;
/* transition order flag (0 = not set, 1 = transition first, 2 = exit first) */
char transition_order_flag;
/* event propagation flag (0 = not set, 1 = block events, 2 = propagate events) */
char event_propagation_flag;
char event_propagation_flag;
/* default comments markup language */
char* markup_language;
size_t markup_language_len;
} CyberiadaMetainformation;
/* SM document */
@@ -178,11 +220,11 @@ typedef struct {
CyberiadaSM* state_machines; /* State machines */
} CyberiadaDocument;
/* SM GraphML supported formats */
/* Cyberiada GraphML Library supported formats */
typedef enum {
cybxmlCyberiada = 0,
cybxmlYED = 1,
cybxmlUnknown = 2
cybxmlCyberiada10 = 0, /* Cyberiada 1.0 format */
cybxmlYED = 1, /* Old YED-based Berloga/Ostranna format */
cybxmlUnknown = 99 /* Format is not specified */
} CyberiadaXMLFormat;
/* -----------------------------------------------------------------------------

4
test.c
View File

@@ -25,12 +25,12 @@
#include "cyberiadaml.h"
const char* formats[] = {
"cyberiada", /* cybxmlCyberiada */
"cyberiada", /* cybxmlCyberiada10 */
"yed" /* cybxmlYED */
};
const char* format_descr[] = {
"Cyberiada-GraphML format",
"Cyberiada-GraphML 1.0 format",
"yEd editor format used by Ostranna projects and the Orbita Simulator"
};