/*. ******* coding:utf-8 AUTOHEADER START v1.1 *******
*. vim: fileencoding=utf-8 syntax=c sw=8 ts=8 et
*.
*. © 2009 David Sommerseth
*. © 2007-2009 Nima Talebi
*.
*. This file is part of Python DMI-Decode.
*.
*. Python DMI-Decode is free software: you can redistribute it and/or modify
*. it under the terms of the GNU General Public License as published by
*. the Free Software Foundation, either version 2 of the License, or
*. (at your option) any later version.
*.
*. Python DMI-Decode 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 General Public License for more details.
*.
*. You should have received a copy of the GNU General Public License
*. along with Python DMI-Decode. If not, see .
*.
*. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
*. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
*. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
*. EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
*. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
*. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
*. OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
*. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*.
*. ADAPTED M. STONE & T. PARKER DISCLAIMER: THIS SOFTWARE COULD RESULT IN INJURY
*. AND/OR DEATH, AND AS SUCH, IT SHOULD NOT BE BUILT, INSTALLED OR USED BY ANYONE.
*.
*. $AutoHeaderSerial::20090522 $
*. ******* AUTOHEADER END v1.1 ******* */
/* Converts XML docs and nodes to Python dicts and lists by
* using an XML file which describes the Python dict layout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* For the avoidance of doubt the "preferred form" of this code is one which
* is in an open unpatent encumbered format. Where cryptographic key signing
* forms part of the process of creating an executable the information
* including keys needed to generate an equivalently functional executable
* are deemed to be part of the source code.
*/
/**
* @file xmlpythonizer.c
* @brief Generic parser for converting XML documents or XML nodes
* into Python Dictionaries
* @author David Sommerseth
* @author Nima Talebi
*/
#include
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "dmixml.h"
#include "dmierror.h"
#include "dmilog.h"
#include "xmlpythonizer.h"
#include "version.h"
#include "compat.h"
/**
* This functions appends a new ptzMAP structure to an already existing chain
* @author David Sommerseth
* @param ptzMAP* Pointer to the chain the new ptzMAP is to be appended
* @param ptzMAP* Pointer to the new ptzMAP to be appended to the already existing ptzMAP
* @return ptzMAP* Pointer to the ptzMAP which includes the newly added ptzMAP
*/
ptzMAP *ptzmap_AppendMap(const ptzMAP *chain, ptzMAP *newmap)
{
if( chain != NULL ) {
newmap->next = (ptzMAP *) chain;
}
return newmap;
}
/**
* This function creates a new ptzMAP mapping record. This defines the key/value relationship in
* the resulting Python Dictionaries.
* @author David Sommerseth
* @param ptzMAP* Pointer to the chain the new mapping will be appended
* @param char* XPath root of the given key and value XPath expressions.
* If NULL, the key and value XPath expressions must be absolute.
* @param ptzTYPES Type of the 'key' value
* @param const char* XPath expression or constant string for the 'key' value
* @param ptzTYPES Type of the 'value' value
* @param const char* XPath expression or constant string for the 'value' value
* @param ptzMAP* Used if the value type is of one of the ptzDICT types, contains a new
* mapping level for the children
* @return ptzMAP* Pointer to the ptzMAP which includes the newly added ptzMAP
*/
ptzMAP *ptzmap_Add(const ptzMAP *chain, char *rootp,
ptzTYPES ktyp, const char *key,
ptzTYPES vtyp, const char *value,
ptzMAP *child)
{
ptzMAP *ret = NULL;
assert( (ktyp == ptzCONST) || (ktyp == ptzSTR) || (ktyp == ptzINT) || (ktyp == ptzFLOAT) );
assert( key != NULL );
ret = (ptzMAP *) malloc(sizeof(ptzMAP)+2);
assert( ret != NULL );
memset(ret, 0, sizeof(ptzMAP)+2);
if( rootp != NULL ) {
ret->rootpath = strdup(rootp);
}
ret->type_key = ktyp;
ret->key = strdup(key);
ret->type_value = vtyp;
if( value != NULL ) {
ret->value = strdup(value);
}
if( child != NULL ) {
ret->child = child;
}
return ptzmap_AppendMap(chain, ret);
};
/**
* This functions sets an ptzLIST typed map entry as a fixed list
* @author David Sommerseth
* @param ptzMAP* Pointer to the ptzMAP elemnt to be updated
* @param const char* Attribute name of the XML node of the 'key' to use as the list index
* @param int Defines the size of the list
*/
void ptzmap_SetFixedList(ptzMAP *map_p, const char *index, int size)
{
assert( map_p != NULL );
switch( map_p->type_value ) {
case ptzLIST_STR:
case ptzLIST_INT:
case ptzLIST_FLOAT:
case ptzLIST_BOOL:
map_p->list_index = strdup(index);
map_p->fixed_list_size = size;
break;
default:
break;
}
}
/**
* This functions frees up a complete pointer chain. This is normally called via #define ptzmap_Free()
* @author David Sommerseth
* @param ptzMAP* Pointer to the ptzMAP to free
*/
void ptzmap_Free_func(ptzMAP *ptr)
{
if( ptr == NULL ) {
return;
}
if( ptr->rootpath != NULL ) {
free(ptr->rootpath);
ptr->rootpath = NULL;
}
if( ptr->list_index != NULL ) {
free(ptr->list_index);
ptr->list_index = NULL;
}
if( ptr->emptyValue != NULL ) {
free(ptr->emptyValue);
ptr->emptyValue = NULL;
}
free(ptr->key);
ptr->key = NULL;
if( ptr->value != NULL ) {
free(ptr->value);
ptr->value = NULL;
}
if( ptr->child != NULL ) {
ptzmap_Free(ptr->child);
}
if( ptr->next != NULL ) {
ptzmap_Free(ptr->next);
}
free(ptr);
}
#if 0
// DEBUG FUNCTIONS
static const char *ptzTYPESstr[] = { "ptzCONST", "ptzSTR", "ptzINT", "ptzFLOAT", "ptzBOOL",
"ptzLIST_STR", "ptzLIST_INT", "ptzLIST_FLOAT", "ptzLIST_BOOL",
"ptzDICT", "ptzLIST_DICT", NULL };
void indent(int lvl)
{
int i = 0;
if( lvl == 0 ) {
return;
}
for( i = 0; i < (lvl * 3); i++ ) {
printf(" ");
}
}
#define ptzmap_Dump(ptr) { ptzmap_Dump_func(ptr, 0); }
void ptzmap_Dump_func(const ptzMAP *ptr, int level)
{
if( ptr == NULL ) {
return;
}
if( ptr->rootpath != NULL ) {
indent(level); printf("root path: %s\n", ptr->rootpath);
}
indent(level); printf("key type: (%i) %-13.13s - key: %s\n",
ptr->type_key, ptzTYPESstr[ptr->type_key], ptr->key);
indent(level); printf("value type: (%i) %-13.13s - value: %s %s\n",
ptr->type_value, ptzTYPESstr[ptr->type_value], ptr->value,
(ptr->emptyIsNone ? "(EmptyIsNone)": ""));
if( ptr->list_index != NULL ) {
indent(level);
printf("List index: %s - Fixed size: %i\n",
ptr->list_index, ptr->fixed_list_size);
}
if( ptr->child != NULL ) {
indent(level); printf(" ** CHILD\n");
ptzmap_Dump_func(ptr->child, level + 1);
indent(level); printf(" ** ---------\n");
}
if( ptr->next != NULL ) {
printf("\n");
ptzmap_Dump_func(ptr->next, level);
}
}
#endif // END OF DEBUG FUNCTIONS
/**
* This functions converts a string to valid ptzTYPES values. This is used when parsing the XML mapping nodes
* @author David Sommerseth
* @param const char* String value containing the key/value type
* @return ptzTYPES The type value
*/
inline ptzTYPES _convert_maptype(Log_t *logp, const char *str) {
if( strcmp(str, "string") == 0 ) {
return ptzSTR;
} else if( strcmp(str, "constant") == 0 ) {
return ptzCONST;
} else if( strcmp(str, "integer") == 0 ) {
return ptzINT;
} else if( strcmp(str, "float") == 0 ) {
return ptzFLOAT;
} else if( strcmp(str, "boolean") == 0 ) {
return ptzBOOL;
} else if( strcmp(str, "list:string") == 0 ) {
return ptzLIST_STR;
} else if( strcmp(str, "list:integer") == 0 ) {
return ptzLIST_INT;
} else if( strcmp(str, "list:float") == 0 ) {
return ptzLIST_FLOAT;
} else if( strcmp(str, "list:boolean") == 0 ) {
return ptzLIST_BOOL;
} else if( strcmp(str, "dict") == 0 ) {
return ptzDICT;
} else if( strcmp(str, "list:dict") == 0 ) {
return ptzLIST_DICT;
} else {
log_append(logp, LOGFL_NORMAL, LOG_WARNING,
"Unknown field type: %s - defaulting to 'constant'", str);
return ptzCONST;
}
}
/**
* This functions is the internal parser - SubMapper (Individual Types of a Group)
* @author David Sommerseth
* @param xmlNode* Node of the starting point for the parsing
* @return ptzMAP* The ptzMAP version of the XML definition
*/
ptzMAP *_do_dmimap_parsing_typeid(Log_t *logp, xmlNode *node) {
ptzMAP *retmap = NULL;
xmlNode *ptr_n = NULL, *map_n = NULL;;
// Go to the next XML_ELEMENT_NODE
foreach_xmlnode(node, map_n) {
if( map_n->type == XML_ELEMENT_NODE ) {
break;
}
}
if( map_n == NULL ) {
PyReturnError(PyExc_NameError, "No mapping nodes were found");
}
// Go to the first