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