Use a hash table for anchors
This commit is contained in:
parent
76c2b57fa6
commit
11a8648818
44
src/attrs.c
44
src/attrs.c
|
@ -904,21 +904,25 @@ static void FreeAnchor(TidyDocImpl* doc, Anchor *a)
|
|||
void TY_(RemoveAnchorByNode)( TidyDocImpl* doc, Node *node )
|
||||
{
|
||||
TidyAttribImpl* attribs = &doc->attribs;
|
||||
Anchor *delme = NULL, *curr, *prev = NULL;
|
||||
Anchor *delme = NULL, *curr, *prev;
|
||||
uint h;
|
||||
|
||||
for ( curr=attribs->anchor_list; curr!=NULL; curr=curr->next )
|
||||
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 )
|
||||
{
|
||||
if ( prev )
|
||||
prev->next = curr->next;
|
||||
else
|
||||
attribs->anchor_list = curr->next;
|
||||
attribs->anchor_hash[h] = curr->next;
|
||||
delme = curr;
|
||||
break;
|
||||
}
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
FreeAnchor( doc, delme );
|
||||
}
|
||||
|
||||
|
@ -935,34 +939,51 @@ 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);
|
||||
|
||||
if ( attribs->anchor_list == NULL)
|
||||
attribs->anchor_list = a;
|
||||
if ( attribs->anchor_hash[h] == NULL)
|
||||
attribs->anchor_hash[h] = a;
|
||||
else
|
||||
{
|
||||
Anchor *here = attribs->anchor_list;
|
||||
Anchor *here = attribs->anchor_hash[h];
|
||||
while (here->next)
|
||||
here = here->next;
|
||||
here->next = a;
|
||||
}
|
||||
|
||||
return attribs->anchor_list;
|
||||
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;
|
||||
tmbstr lname = TY_(tmbstrdup)(doc->allocator, name);
|
||||
lname = TY_(tmbstrtolower)(lname);
|
||||
h = anchorNameHash(lname);
|
||||
|
||||
for ( found = attribs->anchor_list; found != NULL; found = found->next )
|
||||
for ( found = attribs->anchor_hash[h]; found != NULL; found = found->next )
|
||||
{
|
||||
if ( TY_(tmbstrcmp)(found->name, lname) == 0 )
|
||||
break;
|
||||
|
@ -979,11 +1000,14 @@ void TY_(FreeAnchors)( TidyDocImpl* doc )
|
|||
{
|
||||
TidyAttribImpl* attribs = &doc->attribs;
|
||||
Anchor* a;
|
||||
while (NULL != (a = attribs->anchor_list) )
|
||||
uint h;
|
||||
for (h = 0; h < ANCHOR_HASH_SIZE; h++) {
|
||||
while (NULL != (a = attribs->anchor_hash[h]) )
|
||||
{
|
||||
attribs->anchor_list = a->next;
|
||||
attribs->anchor_hash[h] = a->next;
|
||||
FreeAnchor(doc, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* public method for inititializing attribute dictionary */
|
||||
|
|
|
@ -55,10 +55,15 @@ struct _AttrHash
|
|||
typedef struct _AttrHash AttrHash;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
ANCHOR_HASH_SIZE=1021u
|
||||
};
|
||||
|
||||
struct _TidyAttribImpl
|
||||
{
|
||||
/* anchor/node lookup */
|
||||
Anchor* anchor_list;
|
||||
Anchor* anchor_hash[ANCHOR_HASH_SIZE];
|
||||
|
||||
/* Declared literal attributes */
|
||||
Attribute* declared_attr_list;
|
||||
|
|
Loading…
Reference in a new issue