1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-26 00:37:43 +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 */ /* IDs */
XMLPUBFUN int XMLPUBFUN int
xmlAddIDSafe (xmlDocPtr doc, xmlAddIDSafe (xmlAttrPtr attr,
const xmlChar *value, const xmlChar *value);
xmlAttrPtr attr,
int streaming,
xmlIDPtr *id);
XMLPUBFUN xmlIDPtr XMLPUBFUN xmlIDPtr
xmlAddID (xmlValidCtxtPtr ctxt, xmlAddID (xmlValidCtxtPtr ctxt,
xmlDocPtr doc, xmlDocPtr doc,

9
tree.c
View File

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

132
valid.c
View File

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

View File

@@ -222,7 +222,17 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
if (cur->children != NULL) if (cur->children != NULL)
xmlTextReaderFreeNodeList(reader, cur->children); 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) && if ((reader != NULL) && (reader->ctxt != NULL) &&
(reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) { (reader->ctxt->freeAttrsNr < MAX_FREE_NODES)) {
cur->next = reader->ctxt->freeAttrs; 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 * NOTE: the IDness might have already be declared in the DTD
*/ */
if (attr->atype != XML_ATTRIBUTE_ID) { if (attr->atype != XML_ATTRIBUTE_ID) {
xmlIDPtr res;
xmlChar *strip; xmlChar *strip;
int res;
/* /*
* TODO: Use xmlSchemaStrip here; it's not exported at this * TODO: Use xmlSchemaStrip here; it's not exported at this
@@ -5910,8 +5910,10 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
xmlFree((xmlChar *) value); xmlFree((xmlChar *) value);
value = strip; value = strip;
} }
res = xmlAddID(NULL, attr->doc, value, attr); res = xmlAddIDSafe(attr, value);
if (res == NULL) { if (res < 0) {
xmlSchemaPErrMemory(ctxt);
} else if (res == 0) {
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
xmlSchemaPSimpleTypeErr(ctxt, xmlSchemaPSimpleTypeErr(ctxt,
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
@@ -5919,8 +5921,7 @@ xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
NULL, NULL, "Duplicate value '%s' of simple " NULL, NULL, "Duplicate value '%s' of simple "
"type 'xs:ID'", value, NULL); "type 'xs:ID'", value, NULL);
} else }
attr->atype = XML_ATTRIBUTE_ID;
} }
} else if (ret > 0) { } else if (ret > 0) {
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; 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 * NOTE: the IDness might have already be declared in the DTD
*/ */
if (attr->atype != XML_ATTRIBUTE_ID) { if (attr->atype != XML_ATTRIBUTE_ID) {
xmlIDPtr res;
xmlChar *strip; xmlChar *strip;
int res;
strip = xmlSchemaStrip(value); strip = xmlSchemaStrip(value);
if (strip != NULL) { if (strip != NULL) {
res = xmlAddID(NULL, node->doc, strip, attr); res = xmlAddIDSafe(attr, strip);
xmlFree(strip); xmlFree(strip);
} else } else
res = xmlAddID(NULL, node->doc, value, attr); res = xmlAddIDSafe(attr, value);
if (res == NULL) { if (res < 0) {
goto error;
} else if (res == 0) {
ret = 2; ret = 2;
} else {
attr->atype = XML_ATTRIBUTE_ID;
} }
} }
} }