/* * $LynxId: HTAtom.c,v 1.19 2013/11/28 11:11:05 tom Exp $ * * Atoms: Names to numbers HTAtom.c * ======================= * * Atoms are names which are given representative pointer values * so that they can be stored more efficiently, and comparisons * for equality done more efficiently. * * Atoms are kept in a hash table consisting of an array of linked lists. * * Authors: * TBL Tim Berners-Lee, WorldWideWeb project, CERN * (c) Copyright CERN 1991 - See Copyright.html * */ #include #define HASH_SIZE 101 /* Tunable */ #include #include #include #include static HTAtom *hash_table[HASH_SIZE]; static BOOL initialised = NO; /* * To free off all atoms. */ #ifdef LY_FIND_LEAKS static void free_atoms(void); #endif /* * Alternate hashing function. */ #define HASH_FUNCTION(cp_hash) ((strlen(cp_hash) * UCH(*cp_hash)) % HASH_SIZE) HTAtom *HTAtom_for(const char *string) { size_t hash; HTAtom *a; /* First time around, clear hash table */ /* * Memory leak fixed. * 05-29-94 Lynx 2-3-1 Garrett Arch Blythe */ if (!initialised) { int i; for (i = 0; i < HASH_SIZE; i++) hash_table[i] = (HTAtom *) 0; initialised = YES; #ifdef LY_FIND_LEAKS atexit(free_atoms); #endif } /* Generate hash function */ hash = HASH_FUNCTION(string); /* Search for the string in the list */ for (a = hash_table[hash]; a; a = a->next) { if (0 == strcasecomp(a->name, string)) { /* CTRACE((tfp, "HTAtom: Old atom %p for `%s'\n", a, string)); */ return a; /* Found: return it */ } } /* Generate a new entry */ a = (HTAtom *) malloc(sizeof(*a)); if (a == NULL) outofmem(__FILE__, "HTAtom_for"); assert(a != NULL); a->name = (char *) malloc(strlen(string) + 1); if (a->name == NULL) outofmem(__FILE__, "HTAtom_for"); assert(a->name != NULL); strcpy(a->name, string); a->next = hash_table[hash]; /* Put onto the head of list */ hash_table[hash] = a; #ifdef NOT_DEFINED CTRACE((tfp, "HTAtom: New atom %p for `%s'\n", a, string)); #endif /* NOT_DEFINED */ return a; } #ifdef LY_FIND_LEAKS /* * Purpose: Free off all atoms. * Arguments: void * Return Value: void * Remarks/Portability/Dependencies/Restrictions: * To be used at program exit. * Revision History: * 05-29-94 created Lynx 2-3-1 Garrett Arch Blythe */ static void free_atoms(void) { auto int i_counter; HTAtom *HTAp_freeme; /* * Loop through all lists of atoms. */ for (i_counter = 0; i_counter < HASH_SIZE; i_counter++) { /* * Loop through the list. */ while (hash_table[i_counter] != NULL) { /* * Free off atoms and any members. */ HTAp_freeme = hash_table[i_counter]; hash_table[i_counter] = HTAp_freeme->next; FREE(HTAp_freeme->name); FREE(HTAp_freeme); } } } #endif /* LY_FIND_LEAKS */ static BOOL mime_match(const char *name, const char *templ) { if (name && templ) { static char *n1 = NULL; static char *t1 = NULL; char *n2; char *t2; StrAllocCopy(n1, name); /* These also free the ones */ StrAllocCopy(t1, templ); /* from previous call. */ if (!(n2 = StrChr(n1, '/')) || !(t2 = StrChr(t1, '/'))) return NO; *(n2++) = (char) 0; *(t2++) = (char) 0; if ((0 == strcmp(t1, "*") || 0 == strcmp(t1, n1)) && (0 == strcmp(t2, "*") || 0 == strcmp(t2, n2))) return YES; } return NO; } HTList *HTAtom_templateMatches(const char *templ) { HTList *matches = HTList_new(); if (initialised && templ) { int i; HTAtom *cur; for (i = 0; i < HASH_SIZE; i++) { for (cur = hash_table[i]; cur; cur = cur->next) { if (mime_match(cur->name, templ)) HTList_addObject(matches, (void *) cur); } } } return matches; }