1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-02-05 05:47:00 +03:00

valid: Rework xmlAddID

This commit is contained in:
Nick Wellnhofer 2024-02-29 19:38:29 +01:00
parent d57c57ed2f
commit d0d6174e81
6 changed files with 94 additions and 89 deletions

View File

@ -255,11 +255,8 @@ XMLPUBFUN void
/* IDs */
XMLPUBFUN int
xmlAddIDSafe (xmlDocPtr doc,
const xmlChar *value,
xmlAttrPtr attr,
int streaming,
xmlIDPtr *id);
xmlAddIDSafe (xmlAttrPtr attr,
const xmlChar *value);
XMLPUBFUN xmlIDPtr
xmlAddID (xmlValidCtxtPtr ctxt,
xmlDocPtr doc,

9
tree.c
View File

@ -1817,7 +1817,7 @@ xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
if ((value != NULL) && (node != NULL) &&
(xmlIsID(node->doc, node, cur) == 1) &&
(xmlAddIDSafe(node->doc, value, cur, 0, NULL) < 0))
(xmlAddIDSafe(cur, value) < 0))
goto error;
/*
@ -4018,7 +4018,7 @@ xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
id = xmlNodeListGetString(cur->doc, cur->children, 1);
if (id == NULL)
goto error;
res = xmlAddIDSafe(target->doc, id, ret, 0, NULL);
res = xmlAddIDSafe(ret, id);
xmlFree(id);
if (res < 0)
goto error;
@ -6911,7 +6911,7 @@ xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
}
}
if ((prop->atype == XML_ATTRIBUTE_ID) &&
(xmlAddIDSafe(node->doc, value, prop, 0, NULL) < 0)) {
(xmlAddIDSafe(prop, value) < 0)) {
return(NULL);
}
return(prop);
@ -9633,8 +9633,7 @@ end_ns_reference:
idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
if (idVal != NULL) {
if (xmlAddIDSafe(destDoc, idVal, (xmlAttrPtr) cur, 0,
NULL) < 0) {
if (xmlAddIDSafe((xmlAttrPtr) cur, idVal) < 0) {
/* TODO: error message. */
xmlFree(idVal);
goto internal_error;

132
valid.c
View File

@ -2280,35 +2280,36 @@ xmlFreeID(xmlIDPtr id) {
/**
* xmlAddIDSafe:
* @doc: pointer to the document
* @value: the value name
* xmlAddIDInternal:
* @attr: the attribute holding the ID
* @id: pointer to new xmlIdPtr (optional)
* @value: the attribute (ID) value
* @idPtr: pointer to resulting ID
*
* Register a new id declaration
*
* Returns 1 on success, 0 if the ID already exists, -1 if a memory
* allocation fails.
*/
int
xmlAddIDSafe(xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr,
int streaming, xmlIDPtr *id) {
xmlIDPtr ret;
static int
xmlAddIDInternal(xmlAttrPtr attr, const xmlChar *value, xmlIDPtr *idPtr) {
xmlDocPtr doc;
xmlIDPtr id;
xmlIDTablePtr table;
int ret;
if (id != NULL)
*id = NULL;
if (doc == NULL) {
return(-1);
}
if ((value == NULL) || (value[0] == 0)) {
if (idPtr != NULL)
*idPtr = NULL;
if ((value == NULL) || (value[0] == 0))
return(0);
}
if (attr == NULL) {
return(-1);
}
if (attr == NULL)
return(0);
doc = attr->doc;
if (doc == NULL)
return(0);
if (attr->id != NULL)
xmlRemoveID(doc, attr);
/*
* Create the ID table if needed.
@ -2319,69 +2320,63 @@ xmlAddIDSafe(xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr,
if (table == NULL)
return(-1);
} else {
ret = xmlHashLookup(table, value);
if (ret != NULL) {
/*
* Update the attribute unless we are parsing in streaming
* mode. If the attribute is copied from an entity we want
* the ID reference the copy.
*/
if (ret->attr != NULL) {
ret->attr->id = NULL;
ret->attr = attr;
attr->id = ret;
id = xmlHashLookup(table, value);
if (id != NULL) {
if (id->attr != NULL) {
id->attr->id = NULL;
id->attr->atype = 0;
}
ret->lineno = xmlGetLineNo(attr->parent);
attr->atype = XML_ATTRIBUTE_ID;
return(0);
ret = 0;
goto done;
}
}
ret = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
if (ret == NULL)
id = (xmlIDPtr) xmlMalloc(sizeof(xmlID));
if (id == NULL)
return(-1);
memset(ret, 0, sizeof(*ret));
memset(id, 0, sizeof(*id));
/*
* fill the structure.
*/
ret->doc = doc;
ret->value = xmlStrdup(value);
if (ret->value == NULL) {
xmlFreeID(ret);
id->doc = doc;
id->value = xmlStrdup(value);
if (id->value == NULL) {
xmlFreeID(id);
return(-1);
}
if (streaming) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
if (doc->dict != NULL)
ret->name = xmlDictLookup(doc->dict, attr->name, -1);
else
ret->name = xmlStrdup(attr->name);
if (ret->name == NULL) {
xmlFreeID(ret);
return(-1);
}
ret->attr = NULL;
} else {
ret->attr = attr;
ret->name = NULL;
}
ret->lineno = xmlGetLineNo(attr->parent);
if (xmlHashAddEntry(table, value, ret) < 0) {
xmlFreeID(ret);
if (xmlHashAddEntry(table, value, id) < 0) {
xmlFreeID(id);
return(-1);
}
attr->atype = XML_ATTRIBUTE_ID;
if (!streaming)
attr->id = ret;
ret = 1;
if (idPtr != NULL)
*idPtr = id;
if (id != NULL)
*id = ret;
return(1);
done:
id->attr = attr;
id->lineno = xmlGetLineNo(attr->parent);
attr->atype = XML_ATTRIBUTE_ID;
attr->id = id;
return(ret);
}
/**
* xmlAddIDSafe:
* @attr: the attribute holding the ID
* @value: the attribute (ID) value
*
* Register a new id declaration
*
* Returns 1 on success, 0 if the ID already exists, -1 if a memory
* allocation fails.
*/
int
xmlAddIDSafe(xmlAttrPtr attr, const xmlChar *value) {
return(xmlAddIDInternal(attr, value, NULL));
}
/**
@ -2401,7 +2396,10 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
xmlIDPtr id;
int res;
res = xmlAddIDSafe(doc, value, attr, xmlIsStreaming(ctxt), &id);
if ((attr == NULL) || (doc != attr->doc))
return(NULL);
res = xmlAddIDInternal(attr, value, &id);
if (res < 0) {
xmlVErrMemory(ctxt);
}

View File

@ -222,7 +222,17 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
if (cur->children != NULL)
xmlTextReaderFreeNodeList(reader, cur->children);
DICT_FREE(cur->name);
if (cur->id != NULL) {
/*
* Operating in streaming mode, attr is gonna disappear
*/
cur->id->attr = NULL;
cur->id->name = cur->name;
cur->name = NULL;
} else {
DICT_FREE(cur->name);
}
if ((reader != NULL) && (reader->ctxt != NULL) &&
(reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeAttrs;

View File

@ -5898,8 +5898,8 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
* NOTE: the IDness might have already be declared in the DTD
*/
if (attr->atype != XML_ATTRIBUTE_ID) {
xmlIDPtr res;
xmlChar *strip;
int res;
/*
* TODO: Use xmlSchemaStrip here; it's not exported at this
@ -5910,8 +5910,10 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
xmlFree((xmlChar *) value);
value = strip;
}
res = xmlAddID(NULL, attr->doc, value, attr);
if (res == NULL) {
res = xmlAddIDSafe(attr, value);
if (res < 0) {
xmlSchemaPErrMemory(ctxt);
} else if (res == 0) {
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
@ -5919,8 +5921,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
NULL, NULL, "Duplicate value '%s' of simple "
"type 'xs:ID'", value, NULL);
} else
attr->atype = XML_ATTRIBUTE_ID;
}
}
} else if (ret > 0) {
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;

View File

@ -2964,19 +2964,19 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
* NOTE: the IDness might have already be declared in the DTD
*/
if (attr->atype != XML_ATTRIBUTE_ID) {
xmlIDPtr res;
xmlChar *strip;
int res;
strip = xmlSchemaStrip(value);
if (strip != NULL) {
res = xmlAddID(NULL, node->doc, strip, attr);
res = xmlAddIDSafe(attr, strip);
xmlFree(strip);
} else
res = xmlAddID(NULL, node->doc, value, attr);
if (res == NULL) {
res = xmlAddIDSafe(attr, value);
if (res < 0) {
goto error;
} else if (res == 0) {
ret = 2;
} else {
attr->atype = XML_ATTRIBUTE_ID;
}
}
}