src/parse.c devel branch commit 79cae53525

unstable documentation:
  links towards reference texts describing how gem-graph operates
        (and why all the parsed items are useful, compulsory or optional) missing.
  links towards description of the gem-graph model structure (and its XML implementation) missing.

Warning about the word 'node': possible confusion between:
-  the xml tree 'nodes' used in the model xml file and
-  the gem-graph 'nodes' that are local space units used in the geometric space representation
This commit is contained in:
Jean Sirmai 2024-11-01 14:35:31 +01:00
parent 354a53eefb
commit 8003509a72
Signed by: jean
GPG Key ID: FB3115C340E057E3
4 changed files with 287 additions and 131 deletions

View File

@ -1,21 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<gem-graph-model version="0.2.1"> <gem-graph-model version="0.2.1">
<identity> <identity !-- TODO define a key >
<name>Modèle de test</name> <name>model name </name>
<owner>owner</owner>
<owner>Léontine Patinette</owner> <owner_id>owner_id</owner_id>
<date>2021</date>
<owner_id>2</owner_id>
<date>1630000000</date>
<version>1.0</version> <version>1.0</version>
<g_ref id="text" date="date" author="author" lang="en">Ref</g_ref>
<g_ref id="Cause" date="1630000000" author="toujours" lang="en">Ref</g_ref>
</identity> </identity>
<parameters id="texte" date="0" author="Léontine Trottine."> <parameters id="text" date="date" author="author">
<simulation> <simulation>
<max_thread>0</max_thread> <max_thread>0</max_thread>
<max_cycles>9</max_cycles> <max_cycles>9</max_cycles>
@ -42,8 +38,8 @@
<!-- Model objects definition --> <!-- Model objects definition -->
<objects id="only dimers in this model" date="1630000000" author="inanimés,... âme ?"> <objects id="only dimers in this model" date="date" author="author">
<object id="a dimer" date="1630000000" author="Alphonse"> <object id="a dimer" date="date" author="author">
<arrow site="1" weight="1" x="0"/> <arrow site="1" weight="1" x="0"/>
<arrow site="2" weight="1" x="1"/> <arrow site="2" weight="1" x="1"/>
</object> </object>
@ -53,8 +49,8 @@
<!-- Saved space description (initial space is sequence 0) --> <!-- Saved space description (initial space is sequence 0) -->
<savedstates id="texte" date="1630000000" author="Qui courrait dans l'herbe'"> <savedstates id="texte" date="date" author="author">
<state id="initial" date="1630000000" author="Une souris verte"> <state id="initial" date="date" author="author">
<arrow site="0" weight="1" x="0"/> <arrow site="0" weight="1" x="0"/>
<arrow site="1" weight="1" x="1"/> <arrow site="1" weight="1" x="1"/>
<arrow site="0" weight="1" x="10"/> <arrow site="0" weight="1" x="10"/>
@ -73,7 +69,7 @@
<!-- In this version : <xs:sequence minOccurs="0" maxOccurs="unbounded">--> <!-- In this version : <xs:sequence minOccurs="0" maxOccurs="unbounded">-->
<!-- Transitions should be edited by hand and written in a 'human-readable' format --> <!-- Transitions should be edited by hand and written in a 'human-readable' format -->
<conditions id="random walk of dimers" date="1630000000" author="Zazard le lézard !"> <conditions id="random walk of dimers" date="date" author="author">
<condition site="1" weight="1" node_id="1" parent="0" x="0"/> <condition site="1" weight="1" node_id="1" parent="0" x="0"/>
<condition site="2" weight="1" node_id="2" parent="1" x="1"/> <condition site="2" weight="1" node_id="2" parent="1" x="1"/>
@ -93,7 +89,7 @@
<transitions> <transitions>
<transition id="move_a_dimer_to_east" date="1630000000" author="Pas moi..." <transition id="move_a_dimer_to_east" date="date" author="author"
parent="3" probability="1"> parent="3" probability="1">
<arrow site="1" weight="0" x="0"/> <arrow site="1" weight="0" x="0"/>
@ -103,7 +99,7 @@
</transition> </transition>
<transition id="move_a_dimer_to_west" date="1630000000" author="Ni moi !" <transition id="move_a_dimer_to_west" date="date" author="author"
parent="4" probability="1"> parent="4" probability="1">
<arrow site="1" weight="0" x="0"/> <arrow site="1" weight="0" x="0"/>

View File

@ -1,25 +1,32 @@
/* /*
* @file
*
* Gem-graph main file
*
* Gem-graph OpenGL experiments * Gem-graph OpenGL experiments
* *
* Desc: Base header * Desc: Base header
* *
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
*
* This file is part of Gem-graph. * This file is part of Gem-graph.
* *
* This program is free software: you can redistribute it and/or modify * @cond LICENSE
* it under the terms of the GNU Affero General Public License as published by * Copyright © 2021 Libre en Communs <contact@a-lec.org>
* the Free Software Foundation, either version 3 of the License, or * Copyright © 2021-2024 Adrien Bourmault <neox@a-lec.org>
* (at your option) any later version. * Copyright © 2021-2024 Jean Sirmai <jean@a-lec.org>
* *
* This program is distributed in the hope that it will be useful, * This program is free software: you can redistribute it and/or modify it under
* but WITHOUT ANY WARRANTY; without even the implied warranty of * the terms of the GNU Affero General Public License as published by the Free
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Software Foundation, either version 3 of the License, or (at your option) any
* GNU Affero General Public License for more details. * 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 Affero General Public License for more
* details.
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* @endcond
*/ */
#pragma once #pragma once
@ -58,10 +65,9 @@ static inline char *read_file(char *filename); // < used by : init.c
/* /*
* char *read_file(char *filename) reads a file from filename into a provided buffer * char *read_file(char *filename) reads a file from filename into a provided buffer
* *
* @param filename, file name * @param filename
* contents, target ptr
* *
* @return void * @return contents
*/ */
static inline char *read_file(char *filename) static inline char *read_file(char *filename)
{ {

View File

@ -26,18 +26,19 @@
#include <unistd.h> #include <unistd.h>
#include "base.h" #include "base.h"
bool model_init(const char *content, size_t length, const char *basename); bool parse_model_init(const char *content, size_t length, const char *basename);
bool model_shutdown(void); bool parse_model_shutdown(void);
char model_get_dim(void); char parse_model_get_dim(void);
long model_get_dim_value(const char *axis); long parse_model_get_dim_value(const char *axis);
char model_get_multiplicity(void); char parse_model_get_multiplicity(void);
bool model_get_next_state(char *new_state_id); bool parse_model_get_next_space_state(char *new_state_id);
bool model_get_next_arrow(struct arrow_t *new_arrow, bool parse_model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id, const char *state_id,
char dimension); char dimension);
long model_get_state_arrows_count(const char *state_id); long parse_model_get_state_arrows_count(const char *state_id);
bool model_get_next_arrow(struct arrow_t *new_arrow, bool parse_model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id, const char *state_id,
char dimension); char dimension);
void parse_model_test();

View File

@ -1,6 +1,53 @@
/** /**
* @file * @file
* Phantom docs (TODO) *
* XML Gem-graph model parsing functions
*
* -----------------------------------------------------------------------------
*
* @warning about the word '*node*'
*
* A possible confusion between the xml tree '*nodes*' used in the model xml file
* and the gem-graph '*nodes*' that are local space units used in the geometric
* space representation could make this code difficult to understand;
*
* The local name 'node' used alone should be avoided.
*
* In this version, this ambiguity is resolved by using the name "cur_node"
* (current node) for the the xml 'nodes' processed by the parser.
*
* -----------------------------------------------------------------------------
*
* unstable documentation: TODO
* - a link towards reference text describing how gem-graph operates and why
* all the parsed items (compulsory or optional) are useful is missing.
* - a link towards the description of the gem-graph model structure (and its XML
* implementation) is missing.
*
* List of the gem-graph concepts and names (version="0.2.1") parsed here:
* - identity,
* - parameters
* - objects
* - global space (as opposed to local space or working area)
* - dimension (of the space), size
* - topology and limits (of the space): torus, limited area,...
* - <savedstates> (state of the global space)
* - conditions
* - transitions
* - arrow
* - arrow address (site, weight, x, y, z)
* - site
* - node (local space units of the geometric graph)
* - multiplicity (number of sites in each state unit ('cell')
* .
*
* @see space doc (including arrow doc) (TODO)
*
* -----------------------------------------------------------------------------
*
* This file is inherited from a previous development of the Gem-graph server
* then client, in the devel branch commit
* 79cae535258d557e29592a45fbdf426149505738
* *
* This file is part of Gem-graph. * This file is part of Gem-graph.
* *
@ -24,36 +71,59 @@
* @endcond * @endcond
*/ */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <limits.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h> // http://xmlsoft.org/examples/#parse1.c #include <libxml/xmlreader.h> // http://xmlsoft.org/examples/#parse1.c
// https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/general.html // https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/general.html
#include "../include/base.h" #include "../include/base.h"
#define READ_SITE 1 << 0 #define READ_SITE 1 << 0 /**< arrow address = (site, weight, x, y, z) @see arrow doc */
#define READ_WEIGHT 1 << 1 #define READ_WEIGHT 1 << 1 /**< arrow address = (site, weight, x, y, z) @see arrow doc */
#define READ_X 1 << 2 #define READ_X 1 << 2 /**< arrow address = (site, weight, x, y, z) @see arrow doc */
#define READ_Y 1 << 3 #define READ_Y 1 << 3 /**< arrow address = (site, weight, x, y, z) @see arrow doc */
#define READ_Z 1 << 4 #define READ_Z 1 << 4 /**< arrow address = (site, weight, x, y, z) @see arrow doc */
#define SUCCESSFUL_READ_ARROW_X (READ_SITE | READ_WEIGHT | READ_X) /** unstable doc */
#define SUCCESSFUL_READ_ARROW_XY (READ_SITE | READ_WEIGHT | READ_X | READ_Y) #define SUCCESSFUL_READ_ARROW_X (READ_SITE | READ_WEIGHT | READ_X) /**< flag 1D */
#define SUCCESSFUL_READ_ARROW_XYZ (READ_SITE | READ_WEIGHT | READ_X | READ_Y | READ_Z) /** unstable doc */
#define SUCCESSFUL_READ_ARROW_XY (READ_SITE | READ_WEIGHT | READ_X | READ_Y) /**< flag 2D */
/** unstable doc */
#define SUCCESSFUL_READ_ARROW_XYZ (READ_SITE | READ_WEIGHT | READ_X | READ_Y | READ_Z) /**< flag 3D */
static xmlDocPtr model; static xmlDocPtr model;
static xmlHashTablePtr model_hashtable; static xmlHashTablePtr parse_model_hashtable;
bool model_init(const char *content, size_t length, const char *basename) /**
* unstable doc
*
* a debug function
*
* @callgraph parse_model_init()
* @callgraph lseek()
*/
void parse_model_test()
{ {
xmlNode *node;
/* /*
char *content;
char *basename = "data/dimers random walk.xml";
size_t length = lseek(*basename, length, *xxx);
parse_model_init (content, length, "/truc/fichier.xml");
*/
}
/**
* unstable doc
*
* @param *content
* @param length
* @param *basename
*
* @returns bool
*/
bool parse_model_init(const char *content, size_t length, const char *basename)
{
xmlNode *cur_node;
/**
* this initialize the library and check potential ABI mismatches * this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared * between the version it was compiled for and the actual shared
* library used. * library used.
@ -66,23 +136,23 @@ bool model_init(const char *content, size_t length, const char *basename)
return false; return false;
} }
node = xmlDocGetRootElement(model); cur_node = xmlDocGetRootElement(model);
if (node == NULL) { if (cur_node == NULL) {
g_printerr("Empty XML model !\n"); g_printerr("Empty XML model !\n");
xmlFreeDoc(model); xmlFreeDoc(model);
return false; return false;
} }
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) { if (xmlStrcmp(cur_node->name, (xmlChar *) "gem-graph-model")) {
g_printerr("document of the wrong type, root node != gem-graph-model\n"); g_printerr("document of the wrong type, root node != gem-graph-model\n");
xmlFreeDoc(model); xmlFreeDoc(model);
return false; return false;
} }
model_hashtable = xmlHashCreate(0); parse_model_hashtable = xmlHashCreate(0);
if (model_hashtable == NULL) { if (parse_model_hashtable == NULL) {
g_printerr("Can't create model hash table !\n"); g_printerr("Can't create model hash table !\n");
xmlFreeDoc(model); xmlFreeDoc(model);
return false; return false;
@ -91,10 +161,15 @@ bool model_init(const char *content, size_t length, const char *basename)
return true; return true;
} }
bool model_shutdown(void) /**
* unstable doc
*
* @returns bool
*/
bool parse_model_shutdown(void)
{ {
xmlFreeDoc(model); xmlFreeDoc(model);
xmlHashFree(model_hashtable, NULL); xmlHashFree(parse_model_hashtable, NULL);
// Cleanup function for the XML library // Cleanup function for the XML library
xmlCleanupParser(); xmlCleanupParser();
@ -107,15 +182,22 @@ bool model_shutdown(void)
/******************************************************************************/ /******************************************************************************/
static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last) /**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline xmlNodePtr getNextChild(xmlNodePtr cur_node, xmlChar *last)
{ {
while (node != NULL && xmlStrcmp(node->name, last)) { while (cur_node != NULL && xmlStrcmp(cur_node->name, last)) {
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name); // printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(cur_node),
node = node->next; // cur_node->name);
cur_node = cur_node->next;
} }
return node; return cur_node;
} }
/**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline xmlChar* splitStrAtSlash(xmlChar *toSplit) static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
{ {
toSplit = (xmlChar *)xmlStrchr(toSplit, '/'); toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
@ -123,17 +205,24 @@ static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
return toSplit; return toSplit;
} }
/**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline xmlChar* getFirstTag(xmlChar *path) static inline xmlChar* getFirstTag(xmlChar *path)
{ {
xmlChar *preop = path; xmlChar *preop = path;
path = (xmlChar *)xmlStrchr(path, '/'); path = (xmlChar *)xmlStrchr(path, '/');
path = xmlStrsub (path, 1, xmlStrlen(path)); path = xmlStrsub (path, 1, xmlStrlen(path));
//printf("%s = %s + / + %s\n", preop, xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1), path); // printf("%s = %s + / + %s\n", preop,
// xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1), path);
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1); return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
} }
/**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline xmlChar* getLastTag(xmlChar *path) static inline xmlChar* getLastTag(xmlChar *path)
{ {
while ((ulong)xmlStrchr (path, '/')) while ((ulong)xmlStrchr (path, '/'))
@ -145,42 +234,45 @@ static inline xmlChar* getLastTag(xmlChar *path)
/******************************************************************************/ /******************************************************************************/
static xmlNodePtr model_get_node(xmlChar *path) /**
* static doc is ignored by doxygen / consider local helpfulness
*/
static xmlNodePtr parse_model_get_node(xmlChar *path)
{ {
xmlNodePtr node; xmlNodePtr cur_node;
xmlChar *extrait; xmlChar *extrait;
xmlChar *reste, *last; xmlChar *reste, *last;
// Lookup for node from path in hash table // Lookup for cur_node from path in hash table
node = xmlHashLookup(model_hashtable, path); cur_node = xmlHashLookup(parse_model_hashtable, path);
// Found a node in hash table // Found a cur_node in hash table
if (node) { if (cur_node) {
return node; return cur_node;
// no node found in hash table // no cur_node found in hash table
} else { } else {
reste = path; reste = path;
last = getLastTag(reste); last = getLastTag(reste);
node = xmlDocGetRootElement(model); cur_node = xmlDocGetRootElement(model);
while (xmlStrchr (reste, '/')) { while (xmlStrchr (reste, '/')) {
extrait = getFirstTag(reste); extrait = getFirstTag(reste);
reste = splitStrAtSlash((xmlChar *)reste); reste = splitStrAtSlash((xmlChar *)reste);
node = node->xmlChildrenNode; cur_node = cur_node->xmlChildrenNode;
node = getNextChild(node, extrait); cur_node = getNextChild(cur_node, extrait);
} }
if(node && xmlStrcmp(node->name, last)) { if(cur_node && xmlStrcmp(cur_node->name, last)) {
node = node->xmlChildrenNode; cur_node = cur_node->xmlChildrenNode;
while (node && xmlStrcmp(node->name, last)) { while (cur_node && xmlStrcmp(cur_node->name, last)) {
node = node->next; cur_node = cur_node->next;
} }
xmlHashAddEntry (model_hashtable, path, node); xmlHashAddEntry (parse_model_hashtable, path, cur_node);
} }
return node; return cur_node;
} }
@ -189,17 +281,20 @@ static xmlNodePtr model_get_node(xmlChar *path)
/******************************************************************************/ /******************************************************************************/
static inline long model_get_node_long_attrib(xmlNodePtr node, char *id) /**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline long parse_model_get_node_long_attrib(xmlNodePtr cur_node, char *id)
{ {
xmlAttr *attribute; xmlAttr *attribute;
xmlChar* value; xmlChar* value;
long ret_value; long ret_value;
if (node && node->properties) { if (cur_node && cur_node->properties) {
attribute = node->properties; attribute = cur_node->properties;
while(attribute && attribute->name && attribute->children) { while(attribute && attribute->name && attribute->children) {
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) { if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
value = xmlNodeListGetString(node->doc, attribute->children, 1); value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
ret_value = strtol((char *)value, NULL, 0); ret_value = strtol((char *)value, NULL, 0);
xmlFree(value); xmlFree(value);
return ret_value; return ret_value;
@ -210,18 +305,21 @@ static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
return 0; return 0;
} }
static inline bool model_get_node_str_attrib(xmlNodePtr node, /**
* static doc is ignored by doxygen / consider local helpfulness
*/
static inline bool parse_model_get_node_str_attrib(xmlNodePtr cur_node,
char *id, char *id,
char *dest) char *dest)
{ {
xmlAttr *attribute; xmlAttr *attribute;
xmlChar* value; xmlChar* value;
if (node && node->properties) { if (cur_node && cur_node->properties) {
attribute = node->properties; attribute = cur_node->properties;
while(attribute && attribute->name && attribute->children) { while(attribute && attribute->name && attribute->children) {
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) { if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
value = xmlNodeListGetString(node->doc, attribute->children, 1); value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
strcpy(dest, (char *)value); strcpy(dest, (char *)value);
xmlFree(value); xmlFree(value);
return true; return true;
@ -234,45 +332,81 @@ static inline bool model_get_node_str_attrib(xmlNodePtr node,
/******************************************************************************/ /******************************************************************************/
char model_get_dim(void) /**
* unstable doc
*
* 'dim' means here the number of dimensions (x,y,z) of this model space
* @see a reference text explaining that models of any dimension (> 0) can be
* used by gem-graph
*
* @returns 0, 1, 2, or 3
*/
char parse_model_get_dim(void)
{ {
// xmlAttr *attribute; xmlNodePtr cur_node = parse_model_get_node(
// xmlChar* value;
xmlNodePtr node = model_get_node(
(xmlChar *)"parameters/space-param/dimension"); (xmlChar *)"parameters/space-param/dimension");
if (xmlHasProp (node, (xmlChar *) "z")) return 3; if (xmlHasProp (cur_node, (xmlChar *) "z")) return 3;
if (xmlHasProp (node, (xmlChar *) "y")) return 2; if (xmlHasProp (cur_node, (xmlChar *) "y")) return 2;
if (xmlHasProp (node, (xmlChar *) "x")) return 1; if (xmlHasProp (cur_node, (xmlChar *) "x")) return 1;
return 0; return 0;
} }
long model_get_dim_value(const char *axis) /**
* unstable doc
*
* 'dim' means here the number of dimensions (x,y,z) of this model space
* @see a reference text explaining that models of any dimension (> 0) can be
* used by gem-graph
*
* @param *axis
*
* @returns long
*/
long parse_model_get_dim_value(const char *axis)
{ {
// xmlAttr *attribute; // xmlAttr *attribute;
// xmlChar *value; // xmlChar *value;
// long ret_value; // long ret_value;
xmlNodePtr node = model_get_node( xmlNodePtr cur_node = parse_model_get_node(
(xmlChar *)"parameters/space-param/dimension"); (xmlChar *)"parameters/space-param/dimension");
return model_get_node_long_attrib(node, (char *)axis); return parse_model_get_node_long_attrib(cur_node, (char *)axis);
} }
char model_get_multiplicity(void) /**
* unstable doc
*
* 'multiplicity'
* @see arrow doc
*/
char parse_model_get_multiplicity(void)
{ {
// xmlAttr *attribute; // xmlAttr *attribute;
// xmlChar* value; // xmlChar* value;
xmlNodePtr node = model_get_node( xmlNodePtr cur_node = parse_model_get_node(
(xmlChar *)"parameters/space-param/site_multiplicity"); (xmlChar *)"parameters/space-param/site_multiplicity");
if (node->children) if (cur_node->children)
if (node->children->content) if (cur_node->children->content)
return (char)strtol((char *)node->children->content, NULL, 0); return (char)strtol((char *)cur_node->children->content, NULL, 0);
return 0; return 0;
} }
bool model_get_next_state(char *new_state_id) /**
* unstable doc
*
* next *state* is one of the possible states of the global space.
*
* @see a reference text explaining that the gem-graph server calculates successive
* states of a Markov chain from the initial state;
*
* @param *new_state_id
*
* @returns boolean
*/
bool parse_model_get_next_space_state(char *new_state_id)
{ {
static xmlNodePtr cur_node = NULL; static xmlNodePtr cur_node = NULL;
// xmlAttr *attribute; // xmlAttr *attribute;
@ -280,7 +414,7 @@ bool model_get_next_state(char *new_state_id)
if (cur_node == NULL) { if (cur_node == NULL) {
// Get first state // Get first state
cur_node = model_get_node((xmlChar *)"savedstates/state"); cur_node = parse_model_get_node((xmlChar *)"savedstates/state");
} else { } else {
// Get next state // Get next state
@ -291,14 +425,21 @@ bool model_get_next_state(char *new_state_id)
} }
// Lookup in properties // Lookup in properties
if (model_get_node_str_attrib(cur_node, "id", new_state_id)) if (parse_model_get_node_str_attrib(cur_node, "id", new_state_id))
return true; return true;
cur_node = NULL; cur_node = NULL;
return false; return false;
} }
long model_get_state_arrows_count(const char *state_id) /**
* unstable doc
*
* @param *state_id
*
* @returns long
*/
long parse_model_get_state_arrows_count(const char *state_id)
{ {
xmlNodePtr cur_node = NULL; xmlNodePtr cur_node = NULL;
// xmlAttr *attribute; // xmlAttr *attribute;
@ -312,14 +453,14 @@ long model_get_state_arrows_count(const char *state_id)
assert(state_id); assert(state_id);
// Get first state node // Get first state node
cur_node = model_get_node((xmlChar *)"savedstates/state"); cur_node = parse_model_get_node((xmlChar *)"savedstates/state");
// Lookup in properties // Lookup in properties
while (cur_node && cur_node->properties) { while (cur_node && cur_node->properties) {
// attribute = cur_node->properties; < usage ? // attribute = cur_node->properties; < usage ?
// Look for the id attribute // Look for the id attribute
if (model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) { if (parse_model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) {
if (!xmlStrcmp((const xmlChar *)temp_char, (const xmlChar *)state_id)) { if (!xmlStrcmp((const xmlChar *)temp_char, (const xmlChar *)state_id)) {
found = true; found = true;
break; break;
@ -349,7 +490,19 @@ long model_get_state_arrows_count(const char *state_id)
return value; return value;
} }
bool model_get_next_arrow(struct arrow_t *new_arrow, /**
* unstable doc
*
* @see A reference text explaining that the list parsed here describes the
* arrows repartition in the initial state of the space.
*
* @param *new_arrow
* @param *state_id
* @param *dimension
*
* @returns bool
*/
bool parse_model_get_next_arrow(struct arrow_t *new_arrow,
const char *state_id, const char *state_id,
char dimension) char dimension)
{ {
@ -367,14 +520,14 @@ bool model_get_next_arrow(struct arrow_t *new_arrow,
if (cur_node == NULL) { if (cur_node == NULL) {
// Get first state node // Get first state node
cur_node = model_get_node((xmlChar *)"savedstates/state"); cur_node = parse_model_get_node((xmlChar *)"savedstates/state");
// Lookup in properties // Lookup in properties
while (cur_node && cur_node->properties) { while (cur_node && cur_node->properties) {
attribute = cur_node->properties; attribute = cur_node->properties;
// Look for the id attribute // Look for the id attribute
if (model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) { if (parse_model_get_node_str_attrib(cur_node, "id", (char *)&temp_char)) {
if (!xmlStrcmp((xmlChar *)temp_char, (const xmlChar *)state_id)) { if (!xmlStrcmp((xmlChar *)temp_char, (const xmlChar *)state_id)) {
found = true; found = true;
break; break;