CyberiadaML-GraphML 1.0 read/write support according to the CyberiadaML-GraphML Primer document
This commit is contained in:
8
Makefile
8
Makefile
@@ -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
136
cyb_types.c
Normal 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
60
cyb_types.h
Normal 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
|
||||
2751
cyberiadaml.c
2751
cyberiadaml.c
File diff suppressed because it is too large
Load Diff
150
cyberiadaml.h
150
cyberiadaml.h
@@ -38,10 +38,17 @@ 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;
|
||||
@@ -57,7 +64,7 @@ typedef enum {
|
||||
cybActionTransition = 0,
|
||||
cybActionEntry = 1,
|
||||
cybActionExit = 2,
|
||||
cybActionDo = 4,
|
||||
cybActionDo = 4
|
||||
} CyberiadaActionType;
|
||||
|
||||
/* SM node & transitions geometry */
|
||||
@@ -87,6 +94,20 @@ typedef struct _CyberiadaAction {
|
||||
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;
|
||||
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 _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;
|
||||
CyberiadaPoint* geometry_source_point;
|
||||
CyberiadaPoint* geometry_target_point;
|
||||
CyberiadaPolyline* geometry_polyline;
|
||||
CyberiadaPoint* geometry_label;
|
||||
char* color;
|
||||
size_t color_len;
|
||||
struct _CyberiadaEdge* next;
|
||||
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
4
test.c
@@ -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"
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user