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:
Peter Kelly 2012-08-20 10:06:30 +07:00
parent 11a8648818
commit 7fc3255542
4 changed files with 37 additions and 41 deletions

View file

@ -900,28 +900,37 @@ static void FreeAnchor(TidyDocImpl* doc, Anchor *a)
TidyDocFree( doc, 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 */ /* 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; TidyAttribImpl* attribs = &doc->attribs;
Anchor *delme = NULL, *curr, *prev; Anchor *delme = NULL, *curr, *prev = NULL;
uint h; uint h = anchorNameHash(name);
for (h = 0; h < ANCHOR_HASH_SIZE; h++) { for ( curr=attribs->anchor_hash[h]; curr!=NULL; curr=curr->next )
prev = NULL; {
for ( curr=attribs->anchor_hash[h]; curr!=NULL; curr=curr->next ) if ( curr->node == node )
{ {
if ( curr->node == node ) if ( prev )
{ prev->next = curr->next;
if ( prev ) else
prev->next = curr->next; attribs->anchor_hash[h] = curr->next;
else delme = curr;
attribs->anchor_hash[h] = curr->next; break;
delme = curr;
break;
}
prev = curr;
} }
prev = curr;
} }
FreeAnchor( doc, delme ); FreeAnchor( doc, delme );
} }
@ -939,25 +948,12 @@ static Anchor* NewAnchor( TidyDocImpl* doc, ctmbstr name, Node* node )
return a; 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 */ /* add new anchor to namespace */
static Anchor* AddAnchor( TidyDocImpl* doc, ctmbstr name, Node *node ) static Anchor* AddAnchor( TidyDocImpl* doc, ctmbstr name, Node *node )
{ {
uint h;
TidyAttribImpl* attribs = &doc->attribs; TidyAttribImpl* attribs = &doc->attribs;
Anchor *a = NewAnchor( doc, name, node ); Anchor *a = NewAnchor( doc, name, node );
tmbstr lname = TY_(tmbstrdup)(doc->allocator, name); uint h = anchorNameHash(name);
lname = TY_(tmbstrtolower)(lname);
h = anchorNameHash(lname);
if ( attribs->anchor_hash[h] == NULL) if ( attribs->anchor_hash[h] == NULL)
attribs->anchor_hash[h] = a; attribs->anchor_hash[h] = a;
@ -969,19 +965,17 @@ static Anchor* AddAnchor( TidyDocImpl* doc, ctmbstr name, Node *node )
here->next = a; here->next = a;
} }
TidyDocFree(doc, lname);
return attribs->anchor_hash[h]; return attribs->anchor_hash[h];
} }
/* return node associated with anchor */ /* return node associated with anchor */
static Node* GetNodeByAnchor( TidyDocImpl* doc, ctmbstr name ) static Node* GetNodeByAnchor( TidyDocImpl* doc, ctmbstr name )
{ {
uint h;
TidyAttribImpl* attribs = &doc->attribs; TidyAttribImpl* attribs = &doc->attribs;
Anchor *found; Anchor *found;
uint h = anchorNameHash(name);
tmbstr lname = TY_(tmbstrdup)(doc->allocator, name); tmbstr lname = TY_(tmbstrdup)(doc->allocator, name);
lname = TY_(tmbstrtolower)(lname); lname = TY_(tmbstrtolower)(lname);
h = anchorNameHash(lname);
for ( found = attribs->anchor_hash[h]; found != NULL; found = found->next ) for ( found = attribs->anchor_hash[h]; found != NULL; found = found->next )
{ {

View file

@ -122,7 +122,7 @@ Bool TY_(IsValidHTMLID)(ctmbstr id);
Bool TY_(IsValidXMLID)(ctmbstr id); Bool TY_(IsValidXMLID)(ctmbstr id);
/* removes anchor for specific node */ /* removes anchor for specific node */
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, Node *node ); void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, ctmbstr name, Node *node );
/* free all anchors */ /* free all anchors */
void TY_(FreeAnchors)( TidyDocImpl* doc ); void TY_(FreeAnchors)( TidyDocImpl* doc );

View file

@ -2638,17 +2638,19 @@ void TY_(FixAnchors)(TidyDocImpl* doc, Node *node, Bool wantName, Bool wantId)
if (id && !wantId if (id && !wantId
/* make sure that Name has been emitted if requested */ /* 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); TY_(RemoveAttribute)(doc, node, id);
}
if (name && !wantName if (name && !wantName
/* make sure that Id has been emitted if requested */ /* 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); 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) if (node->content)

View file

@ -1077,7 +1077,7 @@ void TY_(FreeAttrs)( TidyDocImpl* doc, Node *node )
if ( (attrIsID(av) || attrIsNAME(av)) && if ( (attrIsID(av) || attrIsNAME(av)) &&
TY_(IsAnchorElement)(doc, node) ) TY_(IsAnchorElement)(doc, node) )
{ {
TY_(RemoveAnchorByNode)( doc, node ); TY_(RemoveAnchorByNode)( doc, av->value, node );
} }
} }