mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03:00
Speed up htmlCheckAutoClose
Switch to binary search.
This commit is contained in:
414
HTMLparser.c
414
HTMLparser.c
@ -1072,102 +1072,266 @@ html40ElementTable[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *oldTag;
|
||||||
|
const char *newTag;
|
||||||
|
} htmlStartCloseEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* start tags that imply the end of current element
|
* start tags that imply the end of current element
|
||||||
*/
|
*/
|
||||||
static const char * const htmlStartClose[] = {
|
static const htmlStartCloseEntry htmlStartClose[] = {
|
||||||
"form", "form", "p", "hr", "h1", "h2", "h3", "h4", "h5", "h6",
|
{ "a", "a" },
|
||||||
"dl", "ul", "ol", "menu", "dir", "address", "pre",
|
{ "a", "fieldset" },
|
||||||
"listing", "xmp", "head", NULL,
|
{ "a", "table" },
|
||||||
"head", "p", NULL,
|
{ "a", "td" },
|
||||||
"title", "p", NULL,
|
{ "a", "th" },
|
||||||
"body", "head", "style", "link", "title", "p", NULL,
|
{ "address", "dd" },
|
||||||
"frameset", "head", "style", "link", "title", "p", NULL,
|
{ "address", "dl" },
|
||||||
"li", "p", "h1", "h2", "h3", "h4", "h5", "h6", "dl", "address",
|
{ "address", "dt" },
|
||||||
"pre", "listing", "xmp", "head", "li", NULL,
|
{ "address", "form" },
|
||||||
"hr", "p", "head", NULL,
|
{ "address", "li" },
|
||||||
"h1", "p", "head", NULL,
|
{ "address", "ul" },
|
||||||
"h2", "p", "head", NULL,
|
{ "b", "center" },
|
||||||
"h3", "p", "head", NULL,
|
{ "b", "p" },
|
||||||
"h4", "p", "head", NULL,
|
{ "b", "td" },
|
||||||
"h5", "p", "head", NULL,
|
{ "b", "th" },
|
||||||
"h6", "p", "head", NULL,
|
{ "big", "p" },
|
||||||
"dir", "p", "head", NULL,
|
{ "caption", "col" },
|
||||||
"address", "p", "head", "ul", NULL,
|
{ "caption", "colgroup" },
|
||||||
"pre", "p", "head", "ul", NULL,
|
{ "caption", "tbody" },
|
||||||
"listing", "p", "head", NULL,
|
{ "caption", "tfoot" },
|
||||||
"xmp", "p", "head", NULL,
|
{ "caption", "thead" },
|
||||||
"blockquote", "p", "head", NULL,
|
{ "caption", "tr" },
|
||||||
"dl", "p", "dt", "menu", "dir", "address", "pre", "listing",
|
{ "col", "col" },
|
||||||
"xmp", "head", NULL,
|
{ "col", "colgroup" },
|
||||||
"dt", "p", "menu", "dir", "address", "pre", "listing", "xmp",
|
{ "col", "tbody" },
|
||||||
"head", "dd", NULL,
|
{ "col", "tfoot" },
|
||||||
"dd", "p", "menu", "dir", "address", "pre", "listing", "xmp",
|
{ "col", "thead" },
|
||||||
"head", "dt", NULL,
|
{ "col", "tr" },
|
||||||
"ul", "p", "head", "ol", "menu", "dir", "address", "pre",
|
{ "colgroup", "colgroup" },
|
||||||
"listing", "xmp", NULL,
|
{ "colgroup", "tbody" },
|
||||||
"ol", "p", "head", "ul", NULL,
|
{ "colgroup", "tfoot" },
|
||||||
"menu", "p", "head", "ul", NULL,
|
{ "colgroup", "thead" },
|
||||||
"p", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", FONTSTYLE, NULL,
|
{ "colgroup", "tr" },
|
||||||
"div", "p", "head", NULL,
|
{ "dd", "dt" },
|
||||||
"noscript", "script", NULL,
|
{ "dir", "dd" },
|
||||||
"center", "font", "b", "i", "p", "head", NULL,
|
{ "dir", "dl" },
|
||||||
"a", "a", "head", NULL,
|
{ "dir", "dt" },
|
||||||
"caption", "p", NULL,
|
{ "dir", "form" },
|
||||||
"colgroup", "caption", "colgroup", "col", "p", NULL,
|
{ "dir", "ul" },
|
||||||
"col", "caption", "col", "p", NULL,
|
{ "dl", "form" },
|
||||||
"table", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6", "pre",
|
{ "dl", "li" },
|
||||||
"listing", "xmp", "a", NULL,
|
{ "dt", "dd" },
|
||||||
"th", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
|
{ "dt", "dl" },
|
||||||
"td", "th", "td", "p", "span", "font", "a", "b", "i", "u", NULL,
|
{ "font", "center" },
|
||||||
"tr", "th", "td", "tr", "caption", "col", "colgroup", "p", NULL,
|
{ "font", "td" },
|
||||||
"thead", "caption", "col", "colgroup", NULL,
|
{ "font", "th" },
|
||||||
"tfoot", "th", "td", "tr", "caption", "col", "colgroup", "thead",
|
{ "form", "form" },
|
||||||
"tbody", "p", NULL,
|
{ "h1", "fieldset" },
|
||||||
"tbody", "th", "td", "tr", "caption", "col", "colgroup", "thead",
|
{ "h1", "form" },
|
||||||
"tfoot", "tbody", "p", NULL,
|
{ "h1", "li" },
|
||||||
"optgroup", "option", NULL,
|
{ "h1", "p" },
|
||||||
"option", "option", NULL,
|
{ "h1", "table" },
|
||||||
"fieldset", "legend", "p", "head", "h1", "h2", "h3", "h4", "h5", "h6",
|
{ "h2", "fieldset" },
|
||||||
"pre", "listing", "xmp", "a", NULL,
|
{ "h2", "form" },
|
||||||
/* most tags in in FONTSTYLE, PHRASE and SPECIAL should close <head> */
|
{ "h2", "li" },
|
||||||
"tt", "head", NULL,
|
{ "h2", "p" },
|
||||||
"i", "head", NULL,
|
{ "h2", "table" },
|
||||||
"b", "head", NULL,
|
{ "h3", "fieldset" },
|
||||||
"u", "head", NULL,
|
{ "h3", "form" },
|
||||||
"s", "head", NULL,
|
{ "h3", "li" },
|
||||||
"strike", "head", NULL,
|
{ "h3", "p" },
|
||||||
"big", "head", NULL,
|
{ "h3", "table" },
|
||||||
"small", "head", NULL,
|
{ "h4", "fieldset" },
|
||||||
|
{ "h4", "form" },
|
||||||
"em", "head", NULL,
|
{ "h4", "li" },
|
||||||
"strong", "head", NULL,
|
{ "h4", "p" },
|
||||||
"dfn", "head", NULL,
|
{ "h4", "table" },
|
||||||
"code", "head", NULL,
|
{ "h5", "fieldset" },
|
||||||
"samp", "head", NULL,
|
{ "h5", "form" },
|
||||||
"kbd", "head", NULL,
|
{ "h5", "li" },
|
||||||
"var", "head", NULL,
|
{ "h5", "p" },
|
||||||
"cite", "head", NULL,
|
{ "h5", "table" },
|
||||||
"abbr", "head", NULL,
|
{ "h6", "fieldset" },
|
||||||
"acronym", "head", NULL,
|
{ "h6", "form" },
|
||||||
|
{ "h6", "li" },
|
||||||
/* "a" */
|
{ "h6", "p" },
|
||||||
"img", "head", NULL,
|
{ "h6", "table" },
|
||||||
/* "applet" */
|
{ "head", "a" },
|
||||||
/* "embed" */
|
{ "head", "abbr" },
|
||||||
/* "object" */
|
{ "head", "acronym" },
|
||||||
"font", "head", NULL,
|
{ "head", "address" },
|
||||||
/* "basefont" */
|
{ "head", "b" },
|
||||||
"br", "head", NULL,
|
{ "head", "bdo" },
|
||||||
/* "script" */
|
{ "head", "big" },
|
||||||
"map", "head", NULL,
|
{ "head", "blockquote" },
|
||||||
"q", "head", NULL,
|
{ "head", "body" },
|
||||||
"sub", "head", NULL,
|
{ "head", "br" },
|
||||||
"sup", "head", NULL,
|
{ "head", "center" },
|
||||||
"span", "head", NULL,
|
{ "head", "cite" },
|
||||||
"bdo", "head", NULL,
|
{ "head", "code" },
|
||||||
"iframe", "head", NULL,
|
{ "head", "dd" },
|
||||||
NULL
|
{ "head", "dfn" },
|
||||||
|
{ "head", "dir" },
|
||||||
|
{ "head", "div" },
|
||||||
|
{ "head", "dl" },
|
||||||
|
{ "head", "dt" },
|
||||||
|
{ "head", "em" },
|
||||||
|
{ "head", "fieldset" },
|
||||||
|
{ "head", "font" },
|
||||||
|
{ "head", "form" },
|
||||||
|
{ "head", "frameset" },
|
||||||
|
{ "head", "h1" },
|
||||||
|
{ "head", "h2" },
|
||||||
|
{ "head", "h3" },
|
||||||
|
{ "head", "h4" },
|
||||||
|
{ "head", "h5" },
|
||||||
|
{ "head", "h6" },
|
||||||
|
{ "head", "hr" },
|
||||||
|
{ "head", "i" },
|
||||||
|
{ "head", "iframe" },
|
||||||
|
{ "head", "img" },
|
||||||
|
{ "head", "kbd" },
|
||||||
|
{ "head", "li" },
|
||||||
|
{ "head", "listing" },
|
||||||
|
{ "head", "map" },
|
||||||
|
{ "head", "menu" },
|
||||||
|
{ "head", "ol" },
|
||||||
|
{ "head", "p" },
|
||||||
|
{ "head", "pre" },
|
||||||
|
{ "head", "q" },
|
||||||
|
{ "head", "s" },
|
||||||
|
{ "head", "samp" },
|
||||||
|
{ "head", "small" },
|
||||||
|
{ "head", "span" },
|
||||||
|
{ "head", "strike" },
|
||||||
|
{ "head", "strong" },
|
||||||
|
{ "head", "sub" },
|
||||||
|
{ "head", "sup" },
|
||||||
|
{ "head", "table" },
|
||||||
|
{ "head", "tt" },
|
||||||
|
{ "head", "u" },
|
||||||
|
{ "head", "ul" },
|
||||||
|
{ "head", "var" },
|
||||||
|
{ "head", "xmp" },
|
||||||
|
{ "hr", "form" },
|
||||||
|
{ "i", "center" },
|
||||||
|
{ "i", "p" },
|
||||||
|
{ "i", "td" },
|
||||||
|
{ "i", "th" },
|
||||||
|
{ "legend", "fieldset" },
|
||||||
|
{ "li", "li" },
|
||||||
|
{ "link", "body" },
|
||||||
|
{ "link", "frameset" },
|
||||||
|
{ "listing", "dd" },
|
||||||
|
{ "listing", "dl" },
|
||||||
|
{ "listing", "dt" },
|
||||||
|
{ "listing", "fieldset" },
|
||||||
|
{ "listing", "form" },
|
||||||
|
{ "listing", "li" },
|
||||||
|
{ "listing", "table" },
|
||||||
|
{ "listing", "ul" },
|
||||||
|
{ "menu", "dd" },
|
||||||
|
{ "menu", "dl" },
|
||||||
|
{ "menu", "dt" },
|
||||||
|
{ "menu", "form" },
|
||||||
|
{ "menu", "ul" },
|
||||||
|
{ "ol", "form" },
|
||||||
|
{ "ol", "ul" },
|
||||||
|
{ "option", "optgroup" },
|
||||||
|
{ "option", "option" },
|
||||||
|
{ "p", "address" },
|
||||||
|
{ "p", "blockquote" },
|
||||||
|
{ "p", "body" },
|
||||||
|
{ "p", "caption" },
|
||||||
|
{ "p", "center" },
|
||||||
|
{ "p", "col" },
|
||||||
|
{ "p", "colgroup" },
|
||||||
|
{ "p", "dd" },
|
||||||
|
{ "p", "dir" },
|
||||||
|
{ "p", "div" },
|
||||||
|
{ "p", "dl" },
|
||||||
|
{ "p", "dt" },
|
||||||
|
{ "p", "fieldset" },
|
||||||
|
{ "p", "form" },
|
||||||
|
{ "p", "frameset" },
|
||||||
|
{ "p", "h1" },
|
||||||
|
{ "p", "h2" },
|
||||||
|
{ "p", "h3" },
|
||||||
|
{ "p", "h4" },
|
||||||
|
{ "p", "h5" },
|
||||||
|
{ "p", "h6" },
|
||||||
|
{ "p", "head" },
|
||||||
|
{ "p", "hr" },
|
||||||
|
{ "p", "li" },
|
||||||
|
{ "p", "listing" },
|
||||||
|
{ "p", "menu" },
|
||||||
|
{ "p", "ol" },
|
||||||
|
{ "p", "p" },
|
||||||
|
{ "p", "pre" },
|
||||||
|
{ "p", "table" },
|
||||||
|
{ "p", "tbody" },
|
||||||
|
{ "p", "td" },
|
||||||
|
{ "p", "tfoot" },
|
||||||
|
{ "p", "th" },
|
||||||
|
{ "p", "title" },
|
||||||
|
{ "p", "tr" },
|
||||||
|
{ "p", "ul" },
|
||||||
|
{ "p", "xmp" },
|
||||||
|
{ "pre", "dd" },
|
||||||
|
{ "pre", "dl" },
|
||||||
|
{ "pre", "dt" },
|
||||||
|
{ "pre", "fieldset" },
|
||||||
|
{ "pre", "form" },
|
||||||
|
{ "pre", "li" },
|
||||||
|
{ "pre", "table" },
|
||||||
|
{ "pre", "ul" },
|
||||||
|
{ "s", "p" },
|
||||||
|
{ "script", "noscript" },
|
||||||
|
{ "small", "p" },
|
||||||
|
{ "span", "td" },
|
||||||
|
{ "span", "th" },
|
||||||
|
{ "strike", "p" },
|
||||||
|
{ "style", "body" },
|
||||||
|
{ "style", "frameset" },
|
||||||
|
{ "tbody", "tbody" },
|
||||||
|
{ "tbody", "tfoot" },
|
||||||
|
{ "td", "tbody" },
|
||||||
|
{ "td", "td" },
|
||||||
|
{ "td", "tfoot" },
|
||||||
|
{ "td", "th" },
|
||||||
|
{ "td", "tr" },
|
||||||
|
{ "tfoot", "tbody" },
|
||||||
|
{ "th", "tbody" },
|
||||||
|
{ "th", "td" },
|
||||||
|
{ "th", "tfoot" },
|
||||||
|
{ "th", "th" },
|
||||||
|
{ "th", "tr" },
|
||||||
|
{ "thead", "tbody" },
|
||||||
|
{ "thead", "tfoot" },
|
||||||
|
{ "title", "body" },
|
||||||
|
{ "title", "frameset" },
|
||||||
|
{ "tr", "tbody" },
|
||||||
|
{ "tr", "tfoot" },
|
||||||
|
{ "tr", "tr" },
|
||||||
|
{ "tt", "p" },
|
||||||
|
{ "u", "p" },
|
||||||
|
{ "u", "td" },
|
||||||
|
{ "u", "th" },
|
||||||
|
{ "ul", "address" },
|
||||||
|
{ "ul", "form" },
|
||||||
|
{ "ul", "menu" },
|
||||||
|
{ "ul", "ol" },
|
||||||
|
{ "ul", "pre" },
|
||||||
|
{ "xmp", "dd" },
|
||||||
|
{ "xmp", "dl" },
|
||||||
|
{ "xmp", "dt" },
|
||||||
|
{ "xmp", "fieldset" },
|
||||||
|
{ "xmp", "form" },
|
||||||
|
{ "xmp", "li" },
|
||||||
|
{ "xmp", "table" },
|
||||||
|
{ "xmp", "ul" }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1237,9 +1401,6 @@ static const elementPriority htmlEndPriority[] = {
|
|||||||
{NULL, 100} /* Default priority */
|
{NULL, 100} /* Default priority */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char** htmlStartCloseIndex[100];
|
|
||||||
static int htmlStartCloseIndexinitialized = 0;
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* *
|
* *
|
||||||
* functions to handle HTML specific data *
|
* functions to handle HTML specific data *
|
||||||
@ -1249,24 +1410,10 @@ static int htmlStartCloseIndexinitialized = 0;
|
|||||||
/**
|
/**
|
||||||
* htmlInitAutoClose:
|
* htmlInitAutoClose:
|
||||||
*
|
*
|
||||||
* Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
|
* This is a no-op now.
|
||||||
* This is not reentrant. Call xmlInitParser() once before processing in
|
|
||||||
* case of use in multithreaded programs.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
htmlInitAutoClose(void) {
|
htmlInitAutoClose(void) {
|
||||||
int indx, i = 0;
|
|
||||||
|
|
||||||
if (htmlStartCloseIndexinitialized) return;
|
|
||||||
|
|
||||||
for (indx = 0;indx < 100;indx ++) htmlStartCloseIndex[indx] = NULL;
|
|
||||||
indx = 0;
|
|
||||||
while ((htmlStartClose[i] != NULL) && (indx < 100 - 1)) {
|
|
||||||
htmlStartCloseIndex[indx++] = (const char**) &htmlStartClose[i];
|
|
||||||
while (htmlStartClose[i] != NULL) i++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
htmlStartCloseIndexinitialized = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1313,6 +1460,19 @@ htmlGetEndPriority (const xmlChar *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
htmlCompareStartClose(const void *vkey, const void *member) {
|
||||||
|
const htmlStartCloseEntry *key = (const htmlStartCloseEntry *) vkey;
|
||||||
|
const htmlStartCloseEntry *entry = (const htmlStartCloseEntry *) member;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = strcmp(key->oldTag, entry->oldTag);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = strcmp(key->newTag, entry->newTag);
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* htmlCheckAutoClose:
|
* htmlCheckAutoClose:
|
||||||
* @newtag: The new tag name
|
* @newtag: The new tag name
|
||||||
@ -1320,37 +1480,21 @@ htmlGetEndPriority (const xmlChar *name) {
|
|||||||
*
|
*
|
||||||
* Checks whether the new tag is one of the registered valid tags for
|
* Checks whether the new tag is one of the registered valid tags for
|
||||||
* closing old.
|
* closing old.
|
||||||
* Initialize the htmlStartCloseIndex for fast lookup of closing tags names.
|
|
||||||
*
|
*
|
||||||
* Returns 0 if no, 1 if yes.
|
* Returns 0 if no, 1 if yes.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag)
|
htmlCheckAutoClose(const xmlChar * newtag, const xmlChar * oldtag)
|
||||||
{
|
{
|
||||||
int i, indx;
|
htmlStartCloseEntry key;
|
||||||
const char **closed = NULL;
|
void *res;
|
||||||
|
|
||||||
if (htmlStartCloseIndexinitialized == 0)
|
key.oldTag = (const char *) oldtag;
|
||||||
htmlInitAutoClose();
|
key.newTag = (const char *) newtag;
|
||||||
|
res = bsearch(&key, htmlStartClose,
|
||||||
/* inefficient, but not a big deal */
|
sizeof(htmlStartClose) / sizeof(htmlStartCloseEntry),
|
||||||
for (indx = 0; indx < 100; indx++) {
|
sizeof(htmlStartCloseEntry), htmlCompareStartClose);
|
||||||
closed = htmlStartCloseIndex[indx];
|
return(res != NULL);
|
||||||
if (closed == NULL)
|
|
||||||
return (0);
|
|
||||||
if (xmlStrEqual(BAD_CAST * closed, newtag))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = closed - htmlStartClose;
|
|
||||||
i++;
|
|
||||||
while (htmlStartClose[i] != NULL) {
|
|
||||||
if (xmlStrEqual(BAD_CAST htmlStartClose[i], oldtag)) {
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user