2021-09-16 21:30:43 +02:00
|
|
|
//=-------------------------------------------------------------------------=//
|
|
|
|
// XML parsing module //
|
|
|
|
// //
|
|
|
|
// Copyright © 2021 The Gem-graph Project //
|
|
|
|
// //
|
|
|
|
// This file is part of gem-graph. //
|
|
|
|
// //
|
|
|
|
// This program is free software: you can redistribute it and/or modify //
|
|
|
|
// it under the terms of the GNU Affero 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 Affero General Public License for more details. //
|
|
|
|
// //
|
|
|
|
// You should have received a copy of the GNU Affero General Public License //
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>. //
|
|
|
|
//=-------------------------------------------------------------------------=//
|
|
|
|
|
2021-09-18 01:00:48 +02:00
|
|
|
#include "../include/parsing.h"
|
2021-09-17 16:14:04 +02:00
|
|
|
#include "../include/model.h"
|
2021-09-16 21:30:43 +02:00
|
|
|
|
2021-09-17 16:14:04 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
2021-09-17 18:40:42 +02:00
|
|
|
// Parsing NOTHING (but yeah that prints) //
|
2021-09-17 16:14:04 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
int parseStubFieldXML (xmlDocPtr doc,
|
|
|
|
ModelParserTableXML_t *ModelTable,
|
|
|
|
int currentParser,
|
|
|
|
xmlNodePtr currentNode)
|
2021-09-16 21:30:43 +02:00
|
|
|
{
|
2021-09-17 18:40:42 +02:00
|
|
|
xmlChar *content, *contentText, *contentValueAttribute;
|
2021-09-17 16:14:04 +02:00
|
|
|
|
2021-09-17 18:40:42 +02:00
|
|
|
contentText = xmlNodeListGetString(doc, currentNode->xmlChildrenNode, 1);
|
|
|
|
contentValueAttribute = xmlGetProp(currentNode,
|
|
|
|
(xmlChar*)"value");
|
|
|
|
|
|
|
|
if (contentText) {
|
|
|
|
content = contentText;
|
|
|
|
} else if (contentValueAttribute) {
|
|
|
|
content = contentValueAttribute;
|
|
|
|
|
|
|
|
// Detect children
|
|
|
|
if (currentNode->xmlChildrenNode) {
|
2021-09-18 01:00:48 +02:00
|
|
|
printLog("%s (stub) has children\n",
|
|
|
|
ModelTable->table[currentParser].tag);
|
2021-09-17 18:40:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-18 01:00:48 +02:00
|
|
|
printLog("%s (stub): %s\n", ModelTable->table[currentParser].tag,
|
2021-09-17 18:40:42 +02:00
|
|
|
content);
|
|
|
|
|
|
|
|
if (!content) {
|
|
|
|
xmlFree(contentText);
|
|
|
|
xmlFree(contentValueAttribute);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlFree(contentText);
|
|
|
|
xmlFree(contentValueAttribute);
|
2021-09-17 16:14:04 +02:00
|
|
|
|
2021-09-16 21:30:43 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-17 16:14:04 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Parsing a text field //
|
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
int parseTextFieldXML (xmlDocPtr doc,
|
|
|
|
ModelParserTableXML_t *ModelTable,
|
|
|
|
int currentParser,
|
|
|
|
xmlNodePtr currentNode)
|
2021-09-16 21:30:43 +02:00
|
|
|
{
|
2021-09-17 18:40:42 +02:00
|
|
|
xmlChar *content, *contentText, *contentValueAttribute;
|
|
|
|
char *destination = (char*)ModelTable->table[currentParser].destination;
|
|
|
|
|
|
|
|
contentText = xmlNodeListGetString(doc, currentNode->xmlChildrenNode, 1);
|
|
|
|
contentValueAttribute = xmlGetProp(currentNode,
|
|
|
|
(xmlChar*)"value");
|
|
|
|
|
|
|
|
if (contentText) {
|
|
|
|
content = contentText;
|
|
|
|
} else if (contentValueAttribute) {
|
|
|
|
content = contentValueAttribute;
|
|
|
|
|
|
|
|
// Detect children
|
|
|
|
if (currentNode->xmlChildrenNode) {
|
|
|
|
printLog("%s has children\n", ModelTable->table[currentParser].tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printLog("%s: %s\n", ModelTable->table[currentParser].tag,
|
|
|
|
content);
|
|
|
|
|
|
|
|
if (!content) {
|
|
|
|
xmlFree(contentText);
|
|
|
|
xmlFree(contentValueAttribute);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcat(destination, " ");
|
|
|
|
strncpy(destination + strlen(destination),
|
|
|
|
(char *)content, MODEL_STRING_SIZE - strlen(destination));
|
|
|
|
|
|
|
|
xmlFree(contentText);
|
|
|
|
xmlFree(contentValueAttribute);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Parsing an integer field //
|
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
int parseIntFieldXML (xmlDocPtr doc,
|
|
|
|
ModelParserTableXML_t *ModelTable,
|
|
|
|
int currentParser,
|
|
|
|
xmlNodePtr currentNode)
|
|
|
|
{
|
|
|
|
xmlChar *content, *contentText, *contentValueAttribute;
|
|
|
|
int *destination = (int*)ModelTable->table[currentParser].destination;
|
|
|
|
|
|
|
|
contentText = xmlNodeListGetString(doc, currentNode->xmlChildrenNode, 1);
|
|
|
|
contentValueAttribute = xmlGetProp(currentNode,
|
|
|
|
(xmlChar*)"value");
|
|
|
|
|
|
|
|
if (contentText) {
|
|
|
|
content = contentText;
|
|
|
|
} else if (contentValueAttribute) {
|
|
|
|
content = contentValueAttribute;
|
|
|
|
|
|
|
|
// Detect children
|
|
|
|
if (currentNode->xmlChildrenNode) {
|
|
|
|
printLog("%s has children\n", ModelTable->table[currentParser].tag);
|
|
|
|
}
|
|
|
|
}
|
2021-09-17 16:14:04 +02:00
|
|
|
|
|
|
|
printLog("%s: %s\n", ModelTable->table[currentParser].tag,
|
|
|
|
content);
|
|
|
|
|
2021-09-17 18:40:42 +02:00
|
|
|
if (!content) {
|
|
|
|
xmlFree(contentText);
|
|
|
|
xmlFree(contentValueAttribute);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*destination = (int)atoi((char*)content);
|
|
|
|
|
2021-09-17 16:14:04 +02:00
|
|
|
xmlFree(content);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-17 16:22:51 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Parsing a field that contains children fields //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2021-09-17 16:14:04 +02:00
|
|
|
int parseParentFieldXML (xmlDocPtr doc,
|
|
|
|
ModelParserTableXML_t *ModelTable,
|
|
|
|
int currentParser,
|
|
|
|
xmlNodePtr currentNode)
|
|
|
|
{
|
2021-09-18 01:00:48 +02:00
|
|
|
printLog("%s parsed\n",
|
|
|
|
ModelTable->table[currentParser].tag);
|
|
|
|
|
|
|
|
// Getting children content
|
2021-09-17 16:14:04 +02:00
|
|
|
currentNode = currentNode->xmlChildrenNode;
|
2021-09-18 01:00:48 +02:00
|
|
|
while (currentNode != NULL) {
|
|
|
|
for (int i = 0; i < ModelTable->len; i++) {
|
|
|
|
if ((!xmlStrcmp(currentNode->name,
|
|
|
|
ModelTable->table[i].tag))) {
|
|
|
|
ModelTable->table[i].parse(doc,
|
|
|
|
ModelTable,
|
|
|
|
i,
|
|
|
|
currentNode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
currentNode = currentNode->next;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-17 18:40:42 +02:00
|
|
|
|
2021-09-18 01:00:48 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Parsing a field that contains children fields with props //
|
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
int parseParentFieldPropsXML (xmlDocPtr doc,
|
|
|
|
ModelParserTableXML_t *ModelTable,
|
|
|
|
int currentParser,
|
|
|
|
xmlNodePtr currentNode)
|
|
|
|
{
|
|
|
|
xmlChar *id, *date, *author;
|
|
|
|
// (truc*)destination = (truc*)ModelTable->table[currentParser].destination;
|
|
|
|
|
|
|
|
// Getting field identity
|
|
|
|
id = xmlGetProp(currentNode, (xmlChar*)"id");
|
|
|
|
date = xmlGetProp(currentNode, (xmlChar*)"date");
|
|
|
|
author = xmlGetProp(currentNode, (xmlChar*)"author");
|
2021-09-17 18:40:42 +02:00
|
|
|
|
2021-09-18 01:00:48 +02:00
|
|
|
printLog("%s parsed (id=%s, date=%s, author=%s)\n",
|
|
|
|
ModelTable->table[currentParser].tag, id, date, author);
|
|
|
|
|
|
|
|
// Getting children content
|
|
|
|
currentNode = currentNode->xmlChildrenNode;
|
2021-09-17 16:14:04 +02:00
|
|
|
while (currentNode != NULL) {
|
|
|
|
for (int i = 0; i < ModelTable->len; i++) {
|
2021-09-16 21:30:43 +02:00
|
|
|
if ((!xmlStrcmp(currentNode->name,
|
2021-09-17 16:14:04 +02:00
|
|
|
ModelTable->table[i].tag))) {
|
|
|
|
ModelTable->table[i].parse(doc,
|
|
|
|
ModelTable,
|
|
|
|
i,
|
|
|
|
currentNode);
|
2021-09-17 18:40:42 +02:00
|
|
|
break;
|
2021-09-16 21:30:43 +02:00
|
|
|
}
|
|
|
|
}
|
2021-09-17 16:14:04 +02:00
|
|
|
currentNode = currentNode->next;
|
|
|
|
}
|
2021-09-16 21:30:43 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-17 16:22:51 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Parsing a model file //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2021-09-16 21:30:43 +02:00
|
|
|
int ParseModelXML(Model_t *model)
|
|
|
|
{
|
2021-09-17 16:14:04 +02:00
|
|
|
ParserTableXML_t table[] =
|
|
|
|
{
|
2021-09-17 18:40:42 +02:00
|
|
|
// IDENTITY
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"identity", parseParentFieldXML, model},
|
|
|
|
{(const xmlChar *)"name", parseTextFieldXML, model->name},
|
|
|
|
{(const xmlChar *)"owner", parseTextFieldXML, model->owner},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
|
|
|
// TODO lacking implementation (model side)
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"owner_id", parseStubFieldXML, model->owner_id},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"date", parseIntFieldXML, &model->date},
|
|
|
|
{(const xmlChar *)"version", parseTextFieldXML, model->version},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
|
|
|
// PARAMETERS
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"parameters", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
// MODELIZATION
|
|
|
|
{(const xmlChar *)"modelization", parseParentFieldXML, model},
|
|
|
|
{(const xmlChar *)"max_thread", parseStubFieldXML, model},
|
|
|
|
{(const xmlChar *)"max_cycles", parseStubFieldXML, model},
|
|
|
|
// SPACE
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"space_param", parseParentFieldXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
{(const xmlChar *)"dimension", parseStubFieldXML, model},
|
|
|
|
{(const xmlChar *)"size", parseStubFieldXML, model},
|
|
|
|
{(const xmlChar *)"site_multiplicity", parseStubFieldXML, model},
|
|
|
|
|
|
|
|
// TODO lacking implementation (model side)
|
|
|
|
{(const xmlChar *)"boundaries", parseStubFieldXML, model},
|
|
|
|
|
|
|
|
// OBJECTS
|
|
|
|
{(const xmlChar *)"objects", parseParentFieldXML, model},
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"object", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
|
|
|
// SPACE
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"space", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
|
|
|
// SAVESTATES
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"savestates", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
|
|
|
|
// TRANSITIONS
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"transitions", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
// TRANSITION
|
|
|
|
// TODO probability
|
2021-09-18 01:00:48 +02:00
|
|
|
{(const xmlChar *)"transition", parseParentFieldPropsXML, model},
|
2021-09-17 18:40:42 +02:00
|
|
|
{(const xmlChar *)"if", parseParentFieldXML, model},
|
|
|
|
{(const xmlChar *)"then", parseParentFieldXML, model},
|
|
|
|
|
|
|
|
// ARROW
|
|
|
|
{(const xmlChar *)"arrow", parseStubFieldXML, model},
|
|
|
|
|
|
|
|
// REF
|
|
|
|
{(const xmlChar *)"ref", parseStubFieldXML, model},
|
|
|
|
|
|
|
|
// QUOTE
|
|
|
|
{(const xmlChar *)"quote", parseStubFieldXML, model},
|
2021-09-17 16:14:04 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
ModelParserTableXML_t modelParserTable =
|
|
|
|
{
|
|
|
|
LEN(table),
|
|
|
|
&table[0]
|
|
|
|
};
|
|
|
|
|
2021-09-16 21:30:43 +02:00
|
|
|
printLog("Parsing model %s\n", model->name);
|
|
|
|
xmlDocPtr xmlDocument;
|
|
|
|
xmlNodePtr currentNode;
|
|
|
|
|
|
|
|
xmlDocument = xmlParseFile(model->filename);
|
|
|
|
|
|
|
|
if (xmlDocument == NULL) {
|
|
|
|
printLog("Can't parse model file at '%s'.\n", model->filename);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentNode = xmlDocGetRootElement(xmlDocument);
|
|
|
|
|
|
|
|
if (currentNode == NULL) {
|
|
|
|
printLog("Invalid model file at '%s', document empty !\n",
|
|
|
|
model->filename);
|
|
|
|
xmlFreeDoc(xmlDocument);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xmlStrcmp(currentNode->name, (const xmlChar *) "gem-graph-model")) {
|
|
|
|
printLog("Invalid model file at '%s', "
|
|
|
|
"root node is not <gem-graph-model> !\n",
|
|
|
|
model->filename);
|
|
|
|
xmlFreeDoc(xmlDocument);
|
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentNode = currentNode->xmlChildrenNode;
|
|
|
|
while (currentNode != NULL) {
|
2021-09-17 16:14:04 +02:00
|
|
|
for (int i = 0; i < modelParserTable.len; i++) {
|
2021-09-16 21:30:43 +02:00
|
|
|
if ((!xmlStrcmp(currentNode->name,
|
2021-09-17 16:14:04 +02:00
|
|
|
modelParserTable.table[i].tag))) {
|
|
|
|
modelParserTable.table[i].parse(xmlDocument,
|
|
|
|
&modelParserTable,
|
|
|
|
i,
|
|
|
|
currentNode);
|
2021-09-16 21:30:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
currentNode = currentNode->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlFreeDoc(xmlDocument);
|
|
|
|
|
|
|
|
// validate when we're finished
|
2021-09-17 18:40:42 +02:00
|
|
|
model->validated = true;
|
2021-09-16 21:30:43 +02:00
|
|
|
return 0;
|
|
|
|
}
|