gambas-source-code/gb.xml/src/element.cpp
Laurent Carlier f1deb8e330 Remove register keyword, deprecated, now reserved keyword with C++17
Fixes "warning: 'register' storage class specifier is deprecated and incompatible with C++17 [-Wdeprecated-register]"
with clang

https://en.cppreference.com/w/cpp/keyword/register
2019-10-30 06:53:09 +00:00

335 lines
10 KiB
C++

/***************************************************************************
(c) 2012 Adrien Prokopowicz <prokopy@users.sourceforge.net>
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, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#include "element.h"
#include "node.h"
#include "utils.h"
#include "textnode.h"
#include <stdlib.h>
#include <memory.h>
/*************************************** Element ***************************************/
Element* XMLElement_New()
{
Element *newElement = (Element*)malloc(sizeof(Element));
memset(newElement, 0, sizeof(Element));
XMLNode_Init(newElement, Node::ElementNode);
return newElement;
}
Element* XMLElement_New(const char *ntagName, size_t nlenTagName)
{
Element *newElement = XMLElement_New();
XMLElement_SetTagName(newElement, ntagName, nlenTagName);
return newElement;
}
void XMLElement_Free(Element *elmt)
{
//Releasing tag name
if(elmt->tagName) free(elmt->tagName);
free(elmt->prefix);
free(elmt->localName);
//Releasing children
XMLNode_clearChildren(elmt);
//Releasing attributes
if(elmt->firstAttribute)
{
for(Attribute *attr = (Attribute*)(elmt->firstAttribute->nextNode); attr != 0; attr = (Attribute*)(attr->nextNode))
{
XMLAttribute_Free((Attribute*)(attr->previousNode));
}
XMLAttribute_Free(elmt->lastAttribute);
}
free(elmt);
}
/***** TagName *****/
void XMLElement_SetTagName(Element *elmt, const char *ntagName, size_t nlenTagName)
{
elmt->lenTagName = nlenTagName;
elmt->tagName = (char*)realloc(elmt->tagName, sizeof(char) * elmt->lenTagName);
memcpy(elmt->tagName, ntagName, nlenTagName);
XMLElement_RefreshPrefix(elmt);
}
void XMLElement_SetPrefix(Element *elmt, const char *nprefix, size_t nlenPrefix)
{
if(nlenPrefix)
{
elmt->tagName = (char*)realloc(elmt->tagName, nlenPrefix + elmt->lenLocalName + 1);
memcpy(elmt->tagName, nprefix, nlenPrefix);
*(elmt->tagName + nlenPrefix) = ':';
memcpy(elmt->tagName + nlenPrefix + 1, elmt->localName, elmt->lenLocalName);
}
else if(elmt->lenPrefix)
{
elmt->tagName = (char*)realloc(elmt->tagName, elmt->lenLocalName);
memcpy(elmt->tagName, elmt->localName, elmt->lenLocalName);
}
elmt->lenPrefix = nlenPrefix;
elmt->prefix = (char*)realloc(elmt->prefix, nlenPrefix);
if(nlenPrefix) memcpy(elmt->prefix, nprefix, nlenPrefix);
}
void XMLElement_RefreshPrefix(Element *elmt)
{
if(!elmt->lenTagName)
{
free(elmt->localName);
elmt->localName = 0;
elmt->lenLocalName = 0;
free(elmt->prefix);
elmt->prefix = 0;
elmt->lenPrefix = 0;
return;
}
char* pos = (char*)memrchr(elmt->tagName, ':', elmt->lenTagName);//Prefix
if(pos)
{
elmt->lenLocalName = (elmt->tagName + elmt->lenTagName) - (pos + 1);
elmt->lenPrefix = pos - elmt->tagName;
elmt->localName = (char*)realloc(elmt->localName, elmt->lenLocalName);
elmt->prefix = (char*)realloc(elmt->prefix, elmt->lenPrefix);
memcpy(elmt->prefix, elmt->tagName, elmt->lenPrefix);
memcpy(elmt->localName, pos + 1, elmt->lenLocalName);
}
else
{
elmt->lenLocalName = elmt->lenTagName;
elmt->localName = (char*)realloc(elmt->localName, sizeof(char) * elmt->lenTagName);
memcpy(elmt->localName, elmt->tagName, elmt->lenTagName);
free(elmt->prefix);
elmt->prefix = 0;
elmt->lenPrefix = 0;
}
}
/***** Attributes *****/
Attribute* XMLElement_AddAttribute(Element *elmt, const char *nattrName, const size_t nlenAttrName)
{
elmt->attributeCount++;
Attribute *newAttribute = XMLAttribute_New(nattrName, nlenAttrName);
newAttribute->parent = elmt;
if(!elmt->lastAttribute)//No attribute
{
elmt->firstAttribute = newAttribute;
elmt->lastAttribute = elmt->firstAttribute;
elmt->lastAttribute->previousNode = 0;
elmt->lastAttribute->nextNode = 0;
return newAttribute;
}
newAttribute->previousNode = elmt->lastAttribute;
elmt->lastAttribute->nextNode = newAttribute;
elmt->lastAttribute = newAttribute;
elmt->lastAttribute->nextNode = 0;
return newAttribute;
}
Attribute* XMLElement_AddAttribute(Element *elmt, const char *nattrName, const size_t nlenAttrName,
const char *nattrVal, const size_t nlenAttrVal)
{
elmt->attributeCount++;
Attribute *newAttribute = XMLAttribute_New(nattrName, nlenAttrName,
nattrVal, nlenAttrVal);
newAttribute->parent = elmt;
if(!elmt->lastAttribute)//No attribute
{
elmt->firstAttribute = newAttribute;
elmt->lastAttribute = elmt->firstAttribute;
elmt->lastAttribute->previousNode = 0;
elmt->lastAttribute->nextNode = 0;
return newAttribute;
}
newAttribute->previousNode = elmt->lastAttribute;
elmt->lastAttribute->nextNode = newAttribute;
elmt->lastAttribute = newAttribute;
elmt->lastAttribute->nextNode = 0;
return newAttribute;
}
Attribute* XMLElement_GetAttribute(const Element *elmt, const char *nattrName, const size_t nlenAttrName, const int mode)
{
for(Attribute *attr = elmt->firstAttribute; attr != 0; attr = (Attribute*)(attr->nextNode))
{
if(GB_MatchString(attr->attrName, attr->lenAttrName, nattrName, nlenAttrName, mode))
return attr;
}
return 0;
}
void XMLElement_SetAttribute(Element *elmt, const char *nattrName, const size_t nlenAttrName,
const char *nattrVal, const size_t nlenAttrVal)
{
Attribute *attr = XMLElement_GetAttribute(elmt, nattrName, nlenAttrName);
if(!attr)
{
XMLElement_AddAttribute(elmt, nattrName, nlenAttrName, nattrVal, nlenAttrVal);
}
else
{
XMLAttribute_SetValue(attr, nattrVal, nlenAttrVal);
}
}
bool XMLElement_AttributeContains(const Element *elmt, const char *attrName, size_t lenAttrName, const char *value, size_t lenValue)
{
Attribute *attr = XMLElement_GetAttribute(elmt, attrName, lenAttrName);
if(!attr) return false;
char *pos = attr->attrValue;
size_t left = attr->lenAttrValue;
while (1) {
if (!memcmp(value, pos, lenValue)) return true;
pos = (char*)memchr(pos, ' ', left);
if (!pos) break;
pos++;
left = attr->lenAttrValue - (pos - attr->attrValue);
}
return false;
}
void XMLElement_RemoveAttribute(Element *elmt, const char *attrName, size_t lenAttrName)
{
XMLElement_RemoveAttribute(elmt, XMLElement_GetAttribute(elmt, attrName,lenAttrName));
}
void XMLElement_RemoveAttribute(Element *elmt, Attribute *attr)
{
if(!attr) return;
if(attr->parent != elmt) return;
if(attr == elmt->firstAttribute) elmt->firstAttribute = (Attribute*)(attr->nextNode);
if(attr == elmt->lastAttribute) elmt->lastAttribute = (Attribute*)(attr->previousNode);
if(attr->nextNode) attr->nextNode->previousNode = attr->previousNode;
if(attr->previousNode) attr->previousNode->nextNode = attr->nextNode;
elmt->attributeCount--;
XMLAttribute_Free(attr);
}
void XMLElement_SetTextContent(Element *elmt, const char *content, size_t lenContent)
{
if(!lenContent) return;
XMLNode_clearChildren(elmt);
TextNode *newChild = XMLTextNode_New(content, lenContent);
XMLNode_appendChild(elmt, newChild);
}
/*************************************** Attribute ***************************************/
Attribute* XMLAttribute_New()
{
Attribute *newAttr = (Attribute*)malloc(sizeof(Attribute));
XMLNode_Init(newAttr, Node::AttributeNode);
newAttr->attrName = 0;
newAttr->attrValue = 0;
newAttr->lenAttrName = 0;
newAttr->lenAttrValue = 0;
return newAttr;
}
Attribute* XMLAttribute_New(const char *nattrName, const size_t nlenAttrName)
{
Attribute *newAttr = (Attribute*)malloc(sizeof(Attribute));
XMLNode_Init(newAttr, Node::AttributeNode);
newAttr->attrValue = 0;
newAttr->lenAttrValue = 0;
newAttr->lenAttrName = nlenAttrName;
newAttr->attrName = (char*)malloc(sizeof(char)*nlenAttrName);
memcpy(newAttr->attrName, nattrName, nlenAttrName);
return newAttr;
}
Attribute* XMLAttribute_New(const char *nattrName, const size_t nlenAttrName,
const char *nattrVal, const size_t nlenAttrVal)
{
Attribute *newAttr = (Attribute*)malloc(sizeof(Attribute));
XMLNode_Init(newAttr, Node::AttributeNode);
newAttr->lenAttrName = nlenAttrName;
newAttr->lenAttrValue = nlenAttrVal;
newAttr->attrName = (char*)malloc(sizeof(char)*(nlenAttrName));
memcpy(newAttr->attrName, nattrName, nlenAttrName);
if(nattrVal && nlenAttrVal)
{
newAttr->attrValue = (char*)malloc(nlenAttrVal);
memcpy(newAttr->attrValue, nattrVal, nlenAttrVal);
}
else
{
newAttr->attrValue = 0;
newAttr->lenAttrValue = 0;
}
return newAttr;
}
void XMLAttribute_Free(Attribute *attr)
{
if(attr->attrName) free(attr->attrName);
if(attr->attrValue) free(attr->attrValue);
free(attr);
attr = 0;
}
void XMLAttribute_SetName(Attribute *attr, const char *nattrName, const size_t nlenAttrName)
{
attr->lenAttrName = nlenAttrName;
attr->attrName = (char*)realloc(attr->attrName, sizeof(char) * attr->lenAttrName);
memcpy(attr->attrName, nattrName, attr->lenAttrName);
}
void XMLAttribute_SetValue(Attribute *attr, const char *nattrVal, const size_t nlenAttrVal)
{
attr->lenAttrValue = nlenAttrVal;
if((!nlenAttrVal) && attr->attrValue)
{
free(attr->attrValue);
attr->attrValue = 0;
return;
}
attr->attrValue = (char*)realloc(attr->attrValue, sizeof(char) * attr->lenAttrValue);
memcpy(attr->attrValue, nattrVal, attr->lenAttrValue);
}