Applied hash table optimisation to RemoveAnchorByNode. This function now takes
the anchor name as a parameter, so it can look in the correct bin. In the case of FreeAttrs, we have the name already (since we found a name or id attribute). In the case of FixAnchors, the anchor name could come from either the name or id attribute, so we call the function separately for each case, passing the appropriate attribute value.
This commit is contained in:
parent
11a8648818
commit
7fc3255542
40
src/attrs.c
40
src/attrs.c
|
@ -900,15 +900,25 @@ static void FreeAnchor(TidyDocImpl* doc, Anchor *a)
|
|||
TidyDocFree( doc, a );
|
||||
}
|
||||
|
||||
static uint anchorNameHash(ctmbstr s)
|
||||
{
|
||||
uint hashval;
|
||||
|
||||
for (hashval = 0; *s != '\0'; s++) {
|
||||
tmbchar c = TY_(ToLower)( *s );
|
||||
hashval = c + 31*hashval;
|
||||
}
|
||||
|
||||
return hashval % ANCHOR_HASH_SIZE;
|
||||
}
|
||||
|
||||
/* removes anchor for specific node */
|
||||
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, Node *node )
|
||||
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, ctmbstr name, Node *node )
|
||||
{
|
||||
TidyAttribImpl* attribs = &doc->attribs;
|
||||
Anchor *delme = NULL, *curr, *prev;
|
||||
uint h;
|
||||
Anchor *delme = NULL, *curr, *prev = NULL;
|
||||
uint h = anchorNameHash(name);
|
||||
|
||||
for (h = 0; h < ANCHOR_HASH_SIZE; h++) {
|
||||
prev = NULL;
|
||||
for ( curr=attribs->anchor_hash[h]; curr!=NULL; curr=curr->next )
|
||||
{
|
||||
if ( curr->node == node )
|
||||
|
@ -922,7 +932,6 @@ void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, Node *node )
|
|||
}
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
FreeAnchor( doc, delme );
|
||||
}
|
||||
|
||||
|
@ -939,25 +948,12 @@ static Anchor* NewAnchor( TidyDocImpl* doc, ctmbstr name, Node* node )
|
|||
return a;
|
||||
}
|
||||
|
||||
static uint anchorNameHash(ctmbstr s)
|
||||
{
|
||||
uint hashval;
|
||||
|
||||
for (hashval = 0; *s != '\0'; s++)
|
||||
hashval = *s + 31*hashval;
|
||||
|
||||
return hashval % ANCHOR_HASH_SIZE;
|
||||
}
|
||||
|
||||
/* add new anchor to namespace */
|
||||
static Anchor* AddAnchor( TidyDocImpl* doc, ctmbstr name, Node *node )
|
||||
{
|
||||
uint h;
|
||||
TidyAttribImpl* attribs = &doc->attribs;
|
||||
Anchor *a = NewAnchor( doc, name, node );
|
||||
tmbstr lname = TY_(tmbstrdup)(doc->allocator, name);
|
||||
lname = TY_(tmbstrtolower)(lname);
|
||||
h = anchorNameHash(lname);
|
||||
uint h = anchorNameHash(name);
|
||||
|
||||
if ( attribs->anchor_hash[h] == NULL)
|
||||
attribs->anchor_hash[h] = a;
|
||||
|
@ -969,19 +965,17 @@ static Anchor* AddAnchor( TidyDocImpl* doc, ctmbstr name, Node *node )
|
|||
here->next = a;
|
||||
}
|
||||
|
||||
TidyDocFree(doc, lname);
|
||||
return attribs->anchor_hash[h];
|
||||
}
|
||||
|
||||
/* return node associated with anchor */
|
||||
static Node* GetNodeByAnchor( TidyDocImpl* doc, ctmbstr name )
|
||||
{
|
||||
uint h;
|
||||
TidyAttribImpl* attribs = &doc->attribs;
|
||||
Anchor *found;
|
||||
uint h = anchorNameHash(name);
|
||||
tmbstr lname = TY_(tmbstrdup)(doc->allocator, name);
|
||||
lname = TY_(tmbstrtolower)(lname);
|
||||
h = anchorNameHash(lname);
|
||||
|
||||
for ( found = attribs->anchor_hash[h]; found != NULL; found = found->next )
|
||||
{
|
||||
|
|
|
@ -122,7 +122,7 @@ Bool TY_(IsValidHTMLID)(ctmbstr id);
|
|||
Bool TY_(IsValidXMLID)(ctmbstr id);
|
||||
|
||||
/* removes anchor for specific node */
|
||||
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, Node *node );
|
||||
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, ctmbstr name, Node *node );
|
||||
|
||||
/* free all anchors */
|
||||
void TY_(FreeAnchors)( TidyDocImpl* doc );
|
||||
|
|
14
src/clean.c
14
src/clean.c
|
@ -2638,17 +2638,19 @@ void TY_(FixAnchors)(TidyDocImpl* doc, Node *node, Bool wantName, Bool wantId)
|
|||
|
||||
if (id && !wantId
|
||||
/* make sure that Name has been emitted if requested */
|
||||
&& (hadName || !wantName || NameEmitted) )
|
||||
&& (hadName || !wantName || NameEmitted) ) {
|
||||
if (!wantId && !wantName)
|
||||
TY_(RemoveAnchorByNode)(doc, id->value, node);
|
||||
TY_(RemoveAttribute)(doc, node, id);
|
||||
}
|
||||
|
||||
if (name && !wantName
|
||||
/* make sure that Id has been emitted if requested */
|
||||
&& (hadId || !wantId || IdEmitted) )
|
||||
&& (hadId || !wantId || IdEmitted) ) {
|
||||
if (!wantId && !wantName)
|
||||
TY_(RemoveAnchorByNode)(doc, name->value, node);
|
||||
TY_(RemoveAttribute)(doc, node, name);
|
||||
|
||||
if (TY_(AttrGetById)(node, TidyAttr_NAME) == NULL &&
|
||||
TY_(AttrGetById)(node, TidyAttr_ID) == NULL)
|
||||
TY_(RemoveAnchorByNode)(doc, node);
|
||||
}
|
||||
}
|
||||
|
||||
if (node->content)
|
||||
|
|
|
@ -1077,7 +1077,7 @@ void TY_(FreeAttrs)( TidyDocImpl* doc, Node *node )
|
|||
if ( (attrIsID(av) || attrIsNAME(av)) &&
|
||||
TY_(IsAnchorElement)(doc, node) )
|
||||
{
|
||||
TY_(RemoveAnchorByNode)( doc, node );
|
||||
TY_(RemoveAnchorByNode)( doc, av->value, node );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue