Skip to content

Commit

Permalink
refs #21: Add functions to get dimension for XML
Browse files Browse the repository at this point in the history
  • Loading branch information
tbeu committed Oct 17, 2017
1 parent 81fd74d commit e4d3377
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 14 deletions.
1 change: 1 addition & 0 deletions ExternData/Examples/package.mo
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ package Examples "Test examples"
Modelica.Blocks.Math.Gain gain1(k=xmlfile.getReal("set1.gain.k")) annotation(Placement(transformation(extent={{-15,60},{5,80}})));
Modelica.Blocks.Math.Gain gain2(k=Modelica.Utilities.Strings.scanReal(xmlfile.getString("set2.gain.k"))) annotation(Placement(transformation(extent={{-15,30},{5,50}})));
Modelica.Blocks.Sources.Clock clock annotation(Placement(transformation(extent={{-50,60},{-30,80}})));
parameter Integer m = xmlfile.getArrayRows2D("table1") "Number of rows in 2D array";
Modelica.Blocks.Sources.TimeTable timeTable(table=xmlfile.getRealArray2D("table1", 3, 2)) annotation(Placement(transformation(extent={{-50,30},{-30,50}})));
equation
connect(clock.y,gain1.u) annotation(Line(points={{-29,70},{-17,70}}, color={0,0,127}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ EXPORTS
ED_getIntFromXML
ED_getDoubleArray1DFromXML
ED_getDoubleArray2DFromXML
ED_getArray1DDimensionFromXML
ED_getArray2DDimensionsFromXML
124 changes: 110 additions & 14 deletions ExternData/Resources/C-Sources/ED_XMLFile.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ void ED_destroyXML(void* _xml)
static char* findValue(XmlNodeRef* root, const char* varName, const char* fileName)
{
char* token = NULL;
char* buf = strdup(varName);
if (buf != NULL) {
char* varNameCopy = strdup(varName);
if (varNameCopy != NULL) {
int elementError = 0;
char* nextToken = NULL;
token = strtok_r(buf, ".", &nextToken);
token = strtok_r(varNameCopy, ".", &nextToken);
if (token == NULL) {
elementError = 1;
}
Expand All @@ -136,7 +136,7 @@ static char* findValue(XmlNodeRef* root, const char* varName, const char* fileNa
elementError = 1;
}
}
free(buf);
free(varNameCopy);
if (0 == elementError) {
XmlNode_getValue(*root, &token);
}
Expand Down Expand Up @@ -256,20 +256,20 @@ void ED_getDoubleArray1DFromXML(void* _xml, const char* varName, double* a, size
iLevel++;
}
if (token != NULL) {
char* buf = strdup(token);
if (buf != NULL) {
char* tokenCopy = strdup(token);
if (tokenCopy != NULL) {
size_t i = 0;
size_t iSibling = 0;
XmlNodeRef parent = XmlNode_getParent(root);
size_t nSiblings = XmlNode_getChildCount(parent);
int line = XmlNode_getLine(root);
int foundSibling = 0;
char* nextToken = NULL;
token = strtok_r(buf, "[]{},; \t", &nextToken);
token = strtok_r(tokenCopy, "[]{},; \t", &nextToken);
while (i < n) {
if (token != NULL) {
if (ED_strtod(token, xml->loc, &a[i++], ED_STRICT)) {
free(buf);
free(tokenCopy);
ModelicaFormatError("Error in line %i: Cannot read double value \"%s\" from file \"%s\"\n",
line, token, xml->fileName);
return;
Expand All @@ -283,12 +283,12 @@ void ED_getDoubleArray1DFromXML(void* _xml, const char* varName, double* a, size
foundSibling = 1;
XmlNode_getValue(child, &token);
line = XmlNode_getLine(child);
free(buf);
free(tokenCopy);
if (token != NULL) {
buf = strdup(token);
if (buf != NULL) {
tokenCopy = strdup(token);
if (tokenCopy != NULL) {
nextToken = NULL;
token = strtok_r(buf, "[]{},; \t", &nextToken);
token = strtok_r(tokenCopy, "[]{},; \t", &nextToken);
}
else {
ModelicaError("Memory allocation error\n");
Expand All @@ -304,7 +304,7 @@ void ED_getDoubleArray1DFromXML(void* _xml, const char* varName, double* a, size
}
else {
/* Error: token is NULL and no (more) siblings */
free(buf);
free(tokenCopy);
if (foundSibling != 0) {
const char* levels[] = {"", "child ", "grandchild ", "great-grandchild ", "great-great-grandchild "};
XmlNodeRef child = XmlNode_getChild(parent, nSiblings - 1);
Expand All @@ -322,7 +322,7 @@ void ED_getDoubleArray1DFromXML(void* _xml, const char* varName, double* a, size
return;
}
}
free(buf);
free(tokenCopy);
}
else {
ModelicaError("Memory allocation error\n");
Expand All @@ -339,3 +339,99 @@ void ED_getDoubleArray2DFromXML(void* _xml, const char* varName, double* a, size
{
ED_getDoubleArray1DFromXML(_xml, varName, a, m*n);
}

void ED_getArray1DDimensionFromXML(void* _xml, const char* varName, int* n)
{
int m;
ED_getArray2DDimensionsFromXML(_xml, varName, &m, n);
*n *= m;
}

void ED_getArray2DDimensionsFromXML(void* _xml, const char* varName, int* m, int* n)
{
XMLFile* xml = (XMLFile*)_xml;
*m = 0;
*n = 0;
ED_PTR_CHECK(xml);
if (xml != NULL) {
XmlNodeRef root = xml->root;
int iLevel = 0;
char* token = findValue(&root, varName, xml->fileName);
while (NULL == token && NULL != root && XmlNode_getChildCount(root) > 0) {
/* Try children if root is empty */
root = XmlNode_getChild(root, 0);
XmlNode_getValue(root, &token);
iLevel++;
}
if (NULL != token) {
char* tokenCopy = strdup(token);
if (NULL != tokenCopy) {
XmlNodeRef parent = XmlNode_getParent(root);
size_t nSiblings = XmlNode_getChildCount(parent);
char* nextToken = NULL;
if (0 == iLevel) {
char* sep = strchr(tokenCopy, ';');
*m = 1;
if (NULL != sep) {
do {
(*m)++;
sep = strchr(sep + 1, ';');
} while (NULL != sep);
}
else {
sep = strchr(tokenCopy, '}');
while (NULL != sep) {
sep = strchr(sep + 1, ',');
if (NULL != sep) {
(*m)++;
sep = strchr(sep + 1, '}');
}
}
}
token = strtok_r(tokenCopy, "[]{},; \t", &nextToken);
if (NULL != token) {
do {
(*n)++;
token = strtok_r(NULL, "[]{},; \t", &nextToken);
} while (NULL != token);
if (0 == *n%*m) {
*n /= *m;
}
else {
*m = 1;
}
}
free(tokenCopy);
}
else {
size_t iSibling;
free(tokenCopy);
for (iSibling = 0; iSibling < nSiblings; iSibling++) {
XmlNodeRef child = XmlNode_getChild(parent, iSibling);
if (XmlNode_isTag(child, XmlNode_getTag(root))) {
XmlNode_getValue(child, &token);
if (NULL != token) {
tokenCopy = strdup(token);
if (NULL != tokenCopy) {
token = strtok_r(tokenCopy, "[]{},; \t", &nextToken);
while (NULL != token) {
(*n)++;
token = strtok_r(NULL, "[]{},; \t", &nextToken);
}
free(tokenCopy);
}
}
}
}
*m = (int)nSiblings;
if (0 == *n%*m) {
*n /= *m;
}
else {
*m = 1;
}
}
}
}
}
}
2 changes: 2 additions & 0 deletions ExternData/Resources/Include/ED_XMLFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@ const char* ED_getStringFromXML(void* _xml, const char* varName, int* exist);
int ED_getIntFromXML(void* _xml, const char* varName, int* exist);
void ED_getDoubleArray1DFromXML(void* _xml, const char* varName, double* a, size_t n);
void ED_getDoubleArray2DFromXML(void* _xml, const char* varName, double* a, size_t m, size_t n);
void ED_getArray1DDimensionFromXML(void* _xml, const char* varName, int* n);
void ED_getArray2DDimensionsFromXML(void* _xml, const char* varName, int* m, int* n);

#endif
57 changes: 57 additions & 0 deletions ExternData/package.mo
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ package ExternData "Library for data I/O of CSV, INI, JSON, MATLAB MAT, TIR, Exc
final function getInteger = Functions.XML.getInteger(final xml=xml) "Get scalar Integer value from XML file" annotation(Documentation(info="<html></html>"));
final function getBoolean = Functions.XML.getBoolean(final xml=xml) "Get scalar Boolean value from XML file" annotation(Documentation(info="<html></html>"));
final function getString = Functions.XML.getString(final xml=xml) "Get scalar String value from XML file" annotation(Documentation(info="<html></html>"));
final function getArraySize1D = Functions.XML.getArraySize1D(final xml=xml) "Get the size of a 1D array in a XML file" annotation(Documentation(info="<html></html>"));
final function getArraySize2D = Functions.XML.getArraySize2D(final xml=xml) "Get the size of a 2D array in a XML file" annotation(Documentation(info="<html></html>"));
final function getArrayRows2D = Functions.XML.getArrayRows2D(final xml=xml) "Get first dimension of 2D array in XML file" annotation(Documentation(info="<html></html>"));
final function getArrayColumns2D = Functions.XML.getArrayColumns2D(final xml=xml) "Get second dimension of 2D array in XML file" annotation(Documentation(info="<html></html>"));
annotation(
Documentation(info="<html><p>Record that wraps the external object <a href=\"modelica://ExternData.Types.ExternXMLFile\">ExternXMLFile</a> and the <a href=\"modelica://ExternData.Functions.XML\">XML</a> read functions for data access of <a href=\"https://en.wikipedia.org/wiki/XML\">XML</a> files.</p><p>See <a href=\"modelica://ExternData.Examples.XMLTest\">Examples.XMLTest</a> for an example.</p></html>"),
defaultComponentName="xmlfile",
Expand Down Expand Up @@ -995,6 +999,59 @@ package ExternData "Library for data I/O of CSV, INI, JSON, MATLAB MAT, TIR, Exc
Include = "#include \"ED_XMLFile.h\"",
Library = {"ED_XMLFile", "bsxml-json", "expat"});
end getString;
function getArraySize1D "Get length of 1D array in XML file"
extends Modelica.Icons.Function;
input String varName "Key";
input Types.ExternXMLFile xml "External XML file object";
output Integer n "Number of elements in array";
external "C" ED_getArray1DDimensionFromXML(xml, varName, n) annotation(
__iti_dll = "ITI_ED_XMLFile.dll",
__iti_dllNoExport = true,
Include = "#include \"ED_XMLFile.h\"",
Library = {"ED_XMLFile", "bsxml-json", "expat"});
end getArraySize1D;
function getArraySize2D "Get dimensions of 2D array in XML file"
extends Modelica.Icons.Function;
input String varName "Key";
input Types.ExternXMLFile xml "External XML file object";
output Integer m "Number of rows in array";
output Integer n "Number of columns in array";
external "C" ED_getArray2DDimensionsFromXML(xml, varName, m, n) annotation(
__iti_dll = "ITI_ED_XMLFile.dll",
__iti_dllNoExport = true,
Include = "#include \"ED_XMLFile.h\"",
Library = {"ED_XMLFile", "bsxml-json", "expat"});
end getArraySize2D;
function getArrayRows2D "Get first dimension of 2D array in XML file"
extends Modelica.Icons.Function;
input String varName "Key";
input Types.ExternXMLFile xml "External XML file object";
output Integer m "Number of rows in array";
protected
Integer n[1] "Number of columns in array";
external "C" ED_getArray2DDimensionsFromXML(xml, varName, m, n) annotation(
__iti_dll = "ITI_ED_XMLFile.dll",
__iti_dllNoExport = true,
Include = "#include \"ED_XMLFile.h\"",
Library = {"ED_XMLFile", "bsxml-json", "expat"});
end getArrayRows2D;
function getArrayColumns2D "Get second dimension of 2D array in XML file"
extends Modelica.Icons.Function;
input String varName "Key";
input Types.ExternXMLFile xml "External XML file object";
output Integer n "Number of columns in array";
protected
Integer m[1] "Number of rows in array";
external "C" ED_getArray2DDimensionsFromXML(xml, varName, m, n) annotation(
__iti_dll = "ITI_ED_XMLFile.dll",
__iti_dllNoExport = true,
Include = "#include \"ED_XMLFile.h\"",
Library = {"ED_XMLFile", "bsxml-json", "expat"});
end getArrayColumns2D;
annotation(Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics={Text(lineColor={128,128,128},extent={{-90,-90},{90,90}},textString="f")}));
end XML;
annotation(Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,100}}), graphics={Text(lineColor={128,128,128},extent={{-90,-90},{90,90}},textString="f")}));
Expand Down

0 comments on commit e4d3377

Please sign in to comment.