diff options
author | Andrew Shadura <andrewsh@debian.org> | 2015-11-01 19:41:28 +0100 |
---|---|---|
committer | Andrew Shadura <andrewsh@debian.org> | 2015-11-01 19:41:28 +0100 |
commit | 61c1a106bd81794f48e4cd85bae129f9270279e8 (patch) | |
tree | 29ecf644c4a13c2645bd8067e66ae8944dd2daf9 /libdigidoc/DigiDocStack.c |
libdigidoc (3.10.1.1208-1) unstable; urgency=medium
* Initial upload (Closes: #658300).
# imported from the archive
Diffstat (limited to 'libdigidoc/DigiDocStack.c')
-rw-r--r-- | libdigidoc/DigiDocStack.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocStack.c b/libdigidoc/DigiDocStack.c new file mode 100644 index 0000000..9ea32e7 --- /dev/null +++ b/libdigidoc/DigiDocStack.c @@ -0,0 +1,315 @@ +//================================================== +// FILE: DigiDocStack.c +// PROJECT: Digi Doc +// DESCRIPTION: Digi Doc functions for simple stack +// to keep track of xml parsing +// AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia +//================================================== +// Copyright (C) AS Sertifitseerimiskeskus +// This library 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 2.1 of the License, or (at your option) any later version. +// This library 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. +// GNU Lesser General Public Licence is available at +// http://www.gnu.org/copyleft/lesser.html +//==========< HISTORY >============================= +// 09.09.2004 Veiko Sinivee +// Creation +//================================================== + +#include <libdigidoc/DigiDocStack.h> +#include <libdigidoc/DigiDocLib.h> +#include <libdigidoc/DigiDocError.h> +#include <libdigidoc/DigiDocDebug.h> +#include <string.h> + +//-------------------------------------------------- +// Finds the last element on stack +// reader - XML reader cursor to current node +// pStack - address of stack begin. This one elemnt +// must exist, but might be initially empty +// return error code or ERR_OK +//-------------------------------------------------- +ElementEntry* ddocStackFindEnd(ElementEntry* pStack) +{ + ElementEntry* pElem = pStack; + while(pElem->pNext) + pElem = (ElementEntry*)pElem->pNext; + return pElem; +} + +//-------------------------------------------------- +// Push a new element info onto stack +// reader - XML reader cursor to current node +// pStack - address of stack begin. This one elemnt +// must exist, but might be initially empty +// pLastElem - address for new elements pointer. +// If not NULL then will be used to return the +// newly allocated elemnt, so you don't have to +// do a new search. +// return error code or ERR_OK +//-------------------------------------------------- +int ddocStackPushElement(ElementEntry* pStack, xmlTextReaderPtr reader, + ElementEntry** pLastElem) +{ + ElementEntry* pElem; + + RETURN_IF_NULL_PARAM(reader); + RETURN_IF_NULL_PARAM(pStack); + pElem = ddocStackFindEnd(pStack); + if(pElem->tag && !pElem->pNext) { // check if this entry is used + pElem->pNext = (ElementEntry*)malloc(sizeof(ElementEntry)); + if(!pElem) + SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); + memset(pElem->pNext, 0, sizeof(ElementEntry)); + pElem = (ElementEntry*)pElem->pNext; + } + if(!pElem) + return ERR_NULL_POINTER; + pElem->tag = xmlTextReaderLocalName(reader); + pElem->prefix = xmlTextReaderPrefix(reader); + pElem->nsUri = xmlTextReaderNamespaceUri(reader); + // atributes + pElem->id = xmlTextReaderGetAttribute(reader, (const xmlChar*)"Id"); + pElem->uri = xmlTextReaderGetAttribute(reader, (const xmlChar*)"URI"); + pElem->content = xmlTextReaderGetAttribute(reader, (const xmlChar*)"ContentType"); + if(pLastElem) // this may be NULL if users doesn't want the last elem. + *pLastElem = pElem; + return ERR_OK; +} + +//-------------------------------------------------- +// Push a new element info onto stack +// tagName - elements tag name, Possibly with ns-prefix +// atts - array of atributa names and values +// pStack - address of stack begin. This one elemnt +// must exist, but might be initially empty +// pLastElem - address for new elements pointer. +// If not NULL then will be used to return the +// newly allocated elemnt, so you don't have to +// do a new search. +// return error code or ERR_OK +//-------------------------------------------------- +int ddocStackPushElementSAX(ElementEntry* pStack, const xmlChar* tagName, + const xmlChar** atts, ElementEntry** pLastElem) +{ + ElementEntry* pElem; + char *p1, *p2; + xmlChar *n, *v; + int i; + + ddocDebug(5, "ddocStackPushElementSAX", "tag: %s", (char*)tagName); + RETURN_IF_NULL_PARAM(tagName) + RETURN_IF_NULL_PARAM(pStack) + pElem = ddocStackFindEnd(pStack); + if(pElem->tag && !pElem->pNext) { // check if this entry is used + pElem->pNext = (ElementEntry*)malloc(sizeof(ElementEntry)); + if(!pElem) + SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); + memset(pElem->pNext, 0, sizeof(ElementEntry)); + pElem = (ElementEntry*)pElem->pNext; + } + if(!pElem) + return ERR_NULL_POINTER; + p1 = (char*)strdup((char*)tagName); + if(!p1) + SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC) + // check for ns-prefix + p2 = strchr(p1, ':'); + if(p2) { + *p2 = 0; + p2++; + pElem->prefix = xmlStrdup((xmlChar*)p1); + if(!pElem->prefix) { + free(p1); + SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); + } + pElem->tag = xmlStrdup((const xmlChar*)p2); + } + else + pElem->tag = xmlStrdup((const xmlChar*)p1); + free(p1); + if(!pElem->tag) + SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC); + for (i = 0; (atts != NULL) && (atts[i] != NULL); i += 2) { + n = (xmlChar*)atts[i]; + v = (xmlChar*)atts[i+1]; + if(n && !strncmp((char*)n, "xmlns", 5) && v) + pElem->nsUri = xmlStrdup((xmlChar*)v); + if(n && !strncmp((char*)n, "Id", 2) && v) + pElem->id = xmlStrdup((xmlChar*)v); + if(n && !strncmp((char*)n, "URI", 3) && v) + pElem->uri = xmlStrdup((xmlChar*)v); + if(n && !strncmp((char*)n, "ContentType", 11) && v) + pElem->content = xmlStrdup((xmlChar*)v); + } + if(pLastElem) // this may be NULL if users doesn't want the last elem. + *pLastElem = pElem; + return ERR_OK; +} + +//-------------------------------------------------- +// Pop the last element from the stack +// pStack - address of stack begin. This one elemnt +// must exist, and will never be deleted. +// bCleanup - flag: 1=cleanup the whole stack, 0=just the last element +// return error code or ERR_OK +// pLastElem - address for new elements pointer. +// If not NULL then will be used to return the +// last element on stack. +//-------------------------------------------------- +int ddocStackPopElement(ElementEntry* pStack, int bCleanup, + ElementEntry** pLastElem) +{ + ElementEntry *pElem = 0, *pOldElem = 0; + + RETURN_IF_NULL_PARAM(pStack); + do { + pOldElem = pElem = pStack; + while(pElem->pNext) { + pOldElem = pElem; + pElem = (ElementEntry *)pElem->pNext; + } + if(pElem && pElem != pStack) { + ddocDebug(5, "ddocStackPopElement", "Pop: %s, cleanup: %d", pElem->tag, bCleanup); + xmlFree(pElem->tag); + pElem->tag = 0; + xmlFree(pElem->prefix); + pElem->prefix = 0; + xmlFree(pElem->nsUri); + pElem->nsUri = 0; + xmlFree(pElem->id); + pElem->id = 0; + xmlFree(pElem->uri); + pElem->uri = 0; + xmlFree(pElem->content); + pElem->content = 0; + free(pElem); + pElem = 0; // mark freed + pOldElem->pNext = 0; + if(!bCleanup) + break; // remove just the last one? + } + } while(pElem && pElem != pStack); + if(bCleanup) { + // now free up also the final first elements + // dynamically allocated part + xmlFree(pStack->tag); + pStack->tag = 0; + xmlFree(pStack->prefix); + pStack->prefix = 0; + xmlFree(pStack->nsUri); + pStack->nsUri = 0; + xmlFree(pStack->id); + pStack->id = 0; + xmlFree(pStack->uri); + pStack->uri = 0; + xmlFree(pStack->content); + pStack->content = 0; + pStack->pNext = 0; + } + if(pLastElem && pElem) // this may be NULL if users doesn't want the last elem. + *pLastElem = pElem; + return ERR_OK; +} + + +//-------------------------------------------------- +// Retrieve the current/last/stack top elements tag (localname) +// pStack - address of stack begin. +//-------------------------------------------------- +const xmlChar* ddocStackCurrentTag(ElementEntry* pStack) +{ + ElementEntry* pElem = 0; + const xmlChar* pTag = 0; + + if(pStack) { + pElem = ddocStackFindEnd(pStack); + if(pElem) + pTag = (const xmlChar*)pElem->tag; + } + return pTag; +} + +//-------------------------------------------------- +// Retrieve the current/last/stack top elements ns prefix +// pStack - address of stack begin. +//-------------------------------------------------- +const xmlChar* ddocStackCurrentNsPrefix(ElementEntry* pStack) +{ + ElementEntry* pElem = 0; + const xmlChar* pPrefix = 0; + + if(pStack) { + pElem = ddocStackFindEnd(pStack); + if(pElem) + pPrefix = (const xmlChar*)pElem->prefix; + } + return pPrefix; +} + + +//-------------------------------------------------- +// Retrieve the current/last/stack top elements ns prefix +// pStack - address of stack begin. +//-------------------------------------------------- +const xmlChar* ddocStackCurrentNsUri(ElementEntry* pStack) +{ + ElementEntry* pElem = 0; + const xmlChar* pUri = 0; + + if(pStack) { + pElem = ddocStackFindEnd(pStack); + if(pElem) + pUri = (const xmlChar*)pElem->nsUri; + } + return pUri; +} + +//-------------------------------------------------- +// Checks if there is a parent element with the given +// localname on the stack. +// pStack - address of stack begin. +// return 1 if there is such a parent elem or 0 if not. +//-------------------------------------------------- +int ddocStackHasParentWithName(ElementEntry* pStack, + const xmlChar* parentsName, ElementEntry* pCurrElem) +{ + int bFound = 0; + ElementEntry *pElem = pStack; + + while(pElem && pElem != pCurrElem) { + if(pElem->tag && !xmlStrcmp(pElem->tag, parentsName)) { + bFound = 1; + break; + } else + pElem = (ElementEntry *)pElem->pNext; + } + return bFound; +} + +//-------------------------------------------------- +// Checks if there is a parent element with the given +// localname on the stack. +// pStack - address of stack begin. +// return 1 if there is such a parent elem or 0 if not. +//-------------------------------------------------- +ElementEntry* ddocStackGetParentWithName(ElementEntry* pStack, + const xmlChar* parentsName, ElementEntry* pCurrElem) +{ + ElementEntry *pParent = 0; + ElementEntry *pElem = pStack; + + while(pElem && pElem != pCurrElem) { + if(pElem->tag && !xmlStrcmp(pElem->tag, parentsName)) { + pParent = pElem; + break; + } else + pElem = (ElementEntry *)pElem->pNext; + } + return pParent; +} |