/* Create new or find old named anchor ** ----------------------------------- ** ** Me one is for a reference which is found in a document, and might ** not be already loaded. ** Note: You are not guaranteed a new anchor -- you might get an old one, ** like with fonts. */ PUBLIC HTAnchor * HTAnchor_findAddress (const char * address) { char *tag = HTParse (address, "", PARSE_VIEW); /* Any tags? */ /* If the address represents a sub-anchor, we recursively load its parent, then we create a child anchor within that document. */ if (*tag) { char *addr = HTParse(address, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); HTParentAnchor * parent = (HTParentAnchor*) HTAnchor_findAddress(addr); HTChildAnchor * child = HTAnchor_findChild(parent, tag); HT_FREE(addr); HT_FREE(tag); return (HTAnchor *) child; } else { /* Else check whether we have this node */ int hash; const char *p; HTList * adults; HTList *grownups; HTParentAnchor * foundAnchor; char *newaddr = NULL; StrAllocCopy(newaddr, address); /* Get our own copy */ HT_FREE(tag); newaddr = HTSimplify(&newaddr); /* Select list from hash table */ for(p=newaddr, hash=0; *p; p++) hash = (int) ((hash * 3 + (*(unsigned char*)p)) % PARENT_HASH_SIZE); if (!adult_table) { if ((adult_table = (HTList* *) HT_CALLOC(PARENT_HASH_SIZE, sizeof(HTList*))) == NULL) HT_OUTOFMEM("HTAnchor_findAddress"); } if (!adult_table[hash]) adult_table[hash] = HTList_new(); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){ if (!strcmp(foundAnchor->address, newaddr)) { HTTRACE(ANCH_TRACE, "Find Parent. %p with address `%s' already exists.\n" _ (void*) foundAnchor _ newaddr); HT_FREE(newaddr); /* We already have it */ return (HTAnchor *) foundAnchor; } } /* Node not found : create new anchor. */ foundAnchor = HTParentAnchor_new(); foundAnchor->address = newaddr; /* Remember our copy */ HTList_addObject (adults, foundAnchor); HTTRACE(ANCH_TRACE, "Find Parent. %p with hash %d and address `%s' created\n" _ (void*)foundAnchor _ hash _ newaddr); return (HTAnchor *) foundAnchor; } }
HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *,address) { char *tag = HTParse (address, "", PARSE_ANCHOR); /* Anchor tag specified ? */ /* If the address represents a sub-anchor, we recursively load its parent, then we create a child anchor within that document. */ if (tag && *tag) { char *docAddress = HTParse(address, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); HTParentAnchor * foundParent = (HTParentAnchor *) HTAnchor_findAddress (docAddress); HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag); free (docAddress); free (tag); return (HTAnchor *) foundAnchor; } else { /* If the address has no anchor tag, check whether we have this node */ int hash; CONST char *p; HTList * adults; HTList *grownups; HTParentAnchor * foundAnchor; if (tag && *tag) free (tag); /* Select list from hash table */ for(p=address, hash=0; *p; p++) hash = (hash * 3 + *p) % HASH_SIZE; if (!adult_table) adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*)); if (!adult_table[hash]) adult_table[hash] = HTList_new(); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; while (foundAnchor = HTList_nextObject (grownups)) { if (equivalent(foundAnchor->address, address)) { if (TRACE) fprintf(stderr, "Anchor %p with address `%s' already exists.\n", foundAnchor, address); return (HTAnchor *) foundAnchor; } } /* Node not found : create new anchor */ foundAnchor = HTParentAnchor_new (); if (TRACE) fprintf(stderr, "New anchor %p has hash %d and address `%s'\n", foundAnchor, hash, address); StrAllocCopy(foundAnchor->address, address); HTList_addObject (adults, foundAnchor); return (HTAnchor *) foundAnchor; } }
/* Data access functions ** --------------------- */ PUBLIC HTParentAnchor * HTAnchor_parent ARGS1( HTAnchor *, me) { if (!me) return NULL; if (me->parent->info) return me->parent->info; /* else: create a new structure */ return HTParentAnchor_new(me->parent); }
/* The address has no anchor tag, for sure. */ PRIVATE HTParentAnchor0 * HTAnchor_findAddress_in_adult_table ARGS1( CONST DocAddress *, newdoc) { /* ** Check whether we have this node. */ int hash; HTList * adults; HTList *grownups; HTParentAnchor0 * foundAnchor; BOOL need_extra_info = (newdoc->post_data || newdoc->post_content_type || newdoc->bookmark || newdoc->isHEAD || newdoc->safe); /* * We need not free adult_table[] atexit - * it should be perfectly empty after free'ing all HText's. * (There is an error if it is not empty at exit). -LP */ /* ** Select list from hash table, */ hash = HASH_FUNCTION(newdoc->address); adults = &(adult_table[hash]); /* ** Search list for anchor. */ grownups = adults; while (NULL != (foundAnchor = (HTParentAnchor0 *)HTList_nextObject(grownups))) { if (HTSEquivalent(foundAnchor->address, newdoc->address) && ((!foundAnchor->info && !need_extra_info) || (foundAnchor->info && HTBEquivalent(foundAnchor->info->post_data, newdoc->post_data) && foundAnchor->info->isHEAD == newdoc->isHEAD))) { CTRACE((tfp, "Anchor %p with address `%s' already exists.\n", (void *)foundAnchor, newdoc->address)); return foundAnchor; } } /* ** Node not found: create new anchor. */ foundAnchor = HTParentAnchor0_new(newdoc->address, hash); CTRACE((tfp, "New anchor %p has hash %d and address `%s'\n", (void *)foundAnchor, hash, newdoc->address)); if (need_extra_info) { /* rare case, create a big structure */ HTParentAnchor *p = HTParentAnchor_new(foundAnchor); if (newdoc->post_data) BStrCopy(p->post_data, newdoc->post_data); if (newdoc->post_content_type) StrAllocCopy(p->post_content_type, newdoc->post_content_type); if (newdoc->bookmark) StrAllocCopy(p->bookmark, newdoc->bookmark); p->isHEAD = newdoc->isHEAD; p->safe = newdoc->safe; } HTList_linkObject(adults, foundAnchor, &foundAnchor->_add_adult); return foundAnchor; }