1 /*
2  * $LynxId: HTAtom.c,v 1.18 2010/09/25 11:43:12 tom Exp $
3  *
4  *			Atoms: Names to numbers			HTAtom.c
5  *			=======================
6  *
7  *	Atoms are names which are given representative pointer values
8  *	so that they can be stored more efficiently, and comparisons
9  *	for equality done more efficiently.
10  *
11  *	Atoms are kept in a hash table consisting of an array of linked lists.
12  *
13  * Authors:
14  *	TBL	Tim Berners-Lee, WorldWideWeb project, CERN
15  *	(c) Copyright CERN 1991 - See Copyright.html
16  *
17  */
18 
19 #include <HTUtils.h>
20 
21 #define HASH_SIZE	101	/* Tunable */
22 #include <HTAtom.h>
23 
24 #include <HTList.h>
25 
26 #include <LYexit.h>
27 #include <LYLeaks.h>
28 
29 static HTAtom *hash_table[HASH_SIZE];
30 static BOOL initialised = NO;
31 
32 /*
33  *	To free off all atoms.
34  */
35 #ifdef LY_FIND_LEAKS
36 static void free_atoms(void);
37 #endif
38 
39 /*
40  *	Alternate hashing function.
41  */
42 #define HASH_FUNCTION(cp_hash) ((strlen(cp_hash) * UCH(*cp_hash)) % HASH_SIZE)
43 
HTAtom_for(const char * string)44 HTAtom *HTAtom_for(const char *string)
45 {
46     size_t hash;
47     HTAtom *a;
48 
49     /* First time around, clear hash table
50      */
51     /*
52      * Memory leak fixed.
53      * 05-29-94 Lynx 2-3-1 Garrett Arch Blythe
54      */
55     if (!initialised) {
56 	int i;
57 
58 	for (i = 0; i < HASH_SIZE; i++)
59 	    hash_table[i] = (HTAtom *) 0;
60 	initialised = YES;
61 #ifdef LY_FIND_LEAKS
62 	atexit(free_atoms);
63 #endif
64     }
65 
66     /*          Generate hash function
67      */
68     hash = HASH_FUNCTION(string);
69 
70     /*          Search for the string in the list
71      */
72     for (a = hash_table[hash]; a; a = a->next) {
73 	if (0 == strcasecomp(a->name, string)) {
74 	    /* CTRACE((tfp, "HTAtom: Old atom %p for `%s'\n", a, string)); */
75 	    return a;		/* Found: return it */
76 	}
77     }
78 
79     /*          Generate a new entry
80      */
81     a = (HTAtom *) malloc(sizeof(*a));
82     if (a == NULL)
83 	outofmem(__FILE__, "HTAtom_for");
84 
85     assert(a != NULL);
86 
87     a->name = (char *) malloc(strlen(string) + 1);
88     if (a->name == NULL)
89 	outofmem(__FILE__, "HTAtom_for");
90 
91     assert(a->name != NULL);
92 
93     strcpy(a->name, string);
94     a->next = hash_table[hash];	/* Put onto the head of list */
95     hash_table[hash] = a;
96 #ifdef NOT_DEFINED
97     CTRACE((tfp, "HTAtom: New atom %p for `%s'\n", a, string));
98 #endif /* NOT_DEFINED */
99     return a;
100 }
101 
102 #ifdef LY_FIND_LEAKS
103 /*
104  *	Purpose:	Free off all atoms.
105  *	Arguments:	void
106  *	Return Value:	void
107  *	Remarks/Portability/Dependencies/Restrictions:
108  *		To be used at program exit.
109  *	Revision History:
110  *		05-29-94	created Lynx 2-3-1 Garrett Arch Blythe
111  */
free_atoms(void)112 static void free_atoms(void)
113 {
114     auto int i_counter;
115     HTAtom *HTAp_freeme;
116 
117     /*
118      * Loop through all lists of atoms.
119      */
120     for (i_counter = 0; i_counter < HASH_SIZE; i_counter++) {
121 	/*
122 	 * Loop through the list.
123 	 */
124 	while (hash_table[i_counter] != NULL) {
125 	    /*
126 	     * Free off atoms and any members.
127 	     */
128 	    HTAp_freeme = hash_table[i_counter];
129 	    hash_table[i_counter] = HTAp_freeme->next;
130 	    FREE(HTAp_freeme->name);
131 	    FREE(HTAp_freeme);
132 	}
133     }
134 }
135 #endif /* LY_FIND_LEAKS */
136 
mime_match(const char * name,const char * templ)137 static BOOL mime_match(const char *name,
138 		       const char *templ)
139 {
140     if (name && templ) {
141 	static char *n1 = NULL;
142 	static char *t1 = NULL;
143 	char *n2;
144 	char *t2;
145 
146 	StrAllocCopy(n1, name);	/* These also free the ones */
147 	StrAllocCopy(t1, templ);	/* from previous call.  */
148 
149 	if (!(n2 = strchr(n1, '/')) || !(t2 = strchr(t1, '/')))
150 	    return NO;
151 
152 	*(n2++) = (char) 0;
153 	*(t2++) = (char) 0;
154 
155 	if ((0 == strcmp(t1, "*") || 0 == strcmp(t1, n1)) &&
156 	    (0 == strcmp(t2, "*") || 0 == strcmp(t2, n2)))
157 	    return YES;
158     }
159     return NO;
160 }
161 
HTAtom_templateMatches(const char * templ)162 HTList *HTAtom_templateMatches(const char *templ)
163 {
164     HTList *matches = HTList_new();
165 
166     if (initialised && templ) {
167 	int i;
168 	HTAtom *cur;
169 
170 	for (i = 0; i < HASH_SIZE; i++) {
171 	    for (cur = hash_table[i]; cur; cur = cur->next) {
172 		if (mime_match(cur->name, templ))
173 		    HTList_addObject(matches, (void *) cur);
174 	    }
175 	}
176     }
177     return matches;
178 }
179