1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "mozilla/Util.h"
39 :
40 : #include "nsHTMLTags.h"
41 : #include "nsCRT.h"
42 : #include "nsReadableUtils.h"
43 : #include "nsString.h"
44 : #include "nsStaticAtom.h"
45 : #include "nsUnicharUtils.h"
46 : #include "mozilla/HashFunctions.h"
47 :
48 : using namespace mozilla;
49 :
50 : // C++ sucks! There's no way to do this with a macro, at least not
51 : // that I know, if you know how to do this with a macro then please do
52 : // so...
53 : static const PRUnichar sHTMLTagUnicodeName_a[] =
54 : {'a', '\0'};
55 : static const PRUnichar sHTMLTagUnicodeName_abbr[] =
56 : {'a', 'b', 'b', 'r', '\0'};
57 : static const PRUnichar sHTMLTagUnicodeName_acronym[] =
58 : {'a', 'c', 'r', 'o', 'n', 'y', 'm', '\0'};
59 : static const PRUnichar sHTMLTagUnicodeName_address[] =
60 : {'a', 'd', 'd', 'r', 'e', 's', 's', '\0'};
61 : static const PRUnichar sHTMLTagUnicodeName_applet[] =
62 : {'a', 'p', 'p', 'l', 'e', 't', '\0'};
63 : static const PRUnichar sHTMLTagUnicodeName_area[] =
64 : {'a', 'r', 'e', 'a', '\0'};
65 : static const PRUnichar sHTMLTagUnicodeName_article[] =
66 : {'a', 'r', 't', 'i', 'c', 'l', 'e', '\0'};
67 : static const PRUnichar sHTMLTagUnicodeName_aside[] =
68 : {'a', 's', 'i', 'd', 'e', '\0'};
69 : #if defined(MOZ_MEDIA)
70 : static const PRUnichar sHTMLTagUnicodeName_audio[] =
71 : {'a', 'u', 'd', 'i', 'o', '\0'};
72 : #endif
73 : static const PRUnichar sHTMLTagUnicodeName_b[] =
74 : {'b', '\0'};
75 : static const PRUnichar sHTMLTagUnicodeName_base[] =
76 : {'b', 'a', 's', 'e', '\0'};
77 : static const PRUnichar sHTMLTagUnicodeName_basefont[] =
78 : {'b', 'a', 's', 'e', 'f', 'o', 'n', 't', '\0'};
79 : static const PRUnichar sHTMLTagUnicodeName_bdo[] =
80 : {'b', 'd', 'o', '\0'};
81 : static const PRUnichar sHTMLTagUnicodeName_bgsound[] =
82 : {'b', 'g', 's', 'o', 'u', 'n', 'd', '\0'};
83 : static const PRUnichar sHTMLTagUnicodeName_big[] =
84 : {'b', 'i', 'g', '\0'};
85 : static const PRUnichar sHTMLTagUnicodeName_blink[] =
86 : {'b', 'l', 'i', 'n', 'k', '\0'};
87 : static const PRUnichar sHTMLTagUnicodeName_blockquote[] =
88 : {'b', 'l', 'o', 'c', 'k', 'q', 'u', 'o', 't', 'e', '\0'};
89 : static const PRUnichar sHTMLTagUnicodeName_body[] =
90 : {'b', 'o', 'd', 'y', '\0'};
91 : static const PRUnichar sHTMLTagUnicodeName_br[] =
92 : {'b', 'r', '\0'};
93 : static const PRUnichar sHTMLTagUnicodeName_button[] =
94 : {'b', 'u', 't', 't', 'o', 'n', '\0'};
95 : static const PRUnichar sHTMLTagUnicodeName_canvas[] =
96 : {'c', 'a', 'n', 'v', 'a', 's', '\0'};
97 : static const PRUnichar sHTMLTagUnicodeName_caption[] =
98 : {'c', 'a', 'p', 't', 'i', 'o', 'n', '\0'};
99 : static const PRUnichar sHTMLTagUnicodeName_center[] =
100 : {'c', 'e', 'n', 't', 'e', 'r', '\0'};
101 : static const PRUnichar sHTMLTagUnicodeName_cite[] =
102 : {'c', 'i', 't', 'e', '\0'};
103 : static const PRUnichar sHTMLTagUnicodeName_code[] =
104 : {'c', 'o', 'd', 'e', '\0'};
105 : static const PRUnichar sHTMLTagUnicodeName_col[] =
106 : {'c', 'o', 'l', '\0'};
107 : static const PRUnichar sHTMLTagUnicodeName_colgroup[] =
108 : {'c', 'o', 'l', 'g', 'r', 'o', 'u', 'p', '\0'};
109 : static const PRUnichar sHTMLTagUnicodeName_counter[] =
110 : {'c', 'o', 'u', 'n', 't', 'e', 'r', '\0'};
111 : static const PRUnichar sHTMLTagUnicodeName_datalist[] =
112 : {'d', 'a', 't', 'a', 'l', 'i', 's', 't', '\0'};
113 : static const PRUnichar sHTMLTagUnicodeName_dd[] =
114 : {'d', 'd', '\0'};
115 : static const PRUnichar sHTMLTagUnicodeName_del[] =
116 : {'d', 'e', 'l', '\0'};
117 : static const PRUnichar sHTMLTagUnicodeName_dfn[] =
118 : {'d', 'f', 'n', '\0'};
119 : static const PRUnichar sHTMLTagUnicodeName_dir[] =
120 : {'d', 'i', 'r', '\0'};
121 : static const PRUnichar sHTMLTagUnicodeName_div[] =
122 : {'d', 'i', 'v', '\0'};
123 : static const PRUnichar sHTMLTagUnicodeName_dl[] =
124 : {'d', 'l', '\0'};
125 : static const PRUnichar sHTMLTagUnicodeName_dt[] =
126 : {'d', 't', '\0'};
127 : static const PRUnichar sHTMLTagUnicodeName_em[] =
128 : {'e', 'm', '\0'};
129 : static const PRUnichar sHTMLTagUnicodeName_embed[] =
130 : {'e', 'm', 'b', 'e', 'd', '\0'};
131 : static const PRUnichar sHTMLTagUnicodeName_fieldset[] =
132 : {'f', 'i', 'e', 'l', 'd', 's', 'e', 't', '\0'};
133 : static const PRUnichar sHTMLTagUnicodeName_figcaption[] =
134 : {'f', 'i', 'g', 'c', 'a', 'p', 't', 'i', 'o', 'n', '\0'};
135 : static const PRUnichar sHTMLTagUnicodeName_figure[] =
136 : {'f', 'i', 'g', 'u', 'r', 'e', '\0'};
137 : static const PRUnichar sHTMLTagUnicodeName_font[] =
138 : {'f', 'o', 'n', 't', '\0'};
139 : static const PRUnichar sHTMLTagUnicodeName_footer[] =
140 : {'f', 'o', 'o', 't', 'e', 'r', '\0'};
141 : static const PRUnichar sHTMLTagUnicodeName_form[] =
142 : {'f', 'o', 'r', 'm', '\0'};
143 : static const PRUnichar sHTMLTagUnicodeName_frame[] =
144 : {'f', 'r', 'a', 'm', 'e', '\0'};
145 : static const PRUnichar sHTMLTagUnicodeName_frameset[] =
146 : {'f', 'r', 'a', 'm', 'e', 's', 'e', 't', '\0'};
147 : static const PRUnichar sHTMLTagUnicodeName_h1[] =
148 : {'h', '1', '\0'};
149 : static const PRUnichar sHTMLTagUnicodeName_h2[] =
150 : {'h', '2', '\0'};
151 : static const PRUnichar sHTMLTagUnicodeName_h3[] =
152 : {'h', '3', '\0'};
153 : static const PRUnichar sHTMLTagUnicodeName_h4[] =
154 : {'h', '4', '\0'};
155 : static const PRUnichar sHTMLTagUnicodeName_h5[] =
156 : {'h', '5', '\0'};
157 : static const PRUnichar sHTMLTagUnicodeName_h6[] =
158 : {'h', '6', '\0'};
159 : static const PRUnichar sHTMLTagUnicodeName_head[] =
160 : {'h', 'e', 'a', 'd', '\0'};
161 : static const PRUnichar sHTMLTagUnicodeName_header[] =
162 : {'h', 'e', 'a', 'd', 'e', 'r', '\0'};
163 : static const PRUnichar sHTMLTagUnicodeName_hgroup[] =
164 : {'h', 'g', 'r', 'o', 'u', 'p', '\0'};
165 : static const PRUnichar sHTMLTagUnicodeName_hr[] =
166 : {'h', 'r', '\0'};
167 : static const PRUnichar sHTMLTagUnicodeName_html[] =
168 : {'h', 't', 'm', 'l', '\0'};
169 : static const PRUnichar sHTMLTagUnicodeName_i[] =
170 : {'i', '\0'};
171 : static const PRUnichar sHTMLTagUnicodeName_iframe[] =
172 : {'i', 'f', 'r', 'a', 'm', 'e', '\0'};
173 : static const PRUnichar sHTMLTagUnicodeName_image[] =
174 : {'i', 'm', 'a', 'g', 'e', '\0'};
175 : static const PRUnichar sHTMLTagUnicodeName_img[] =
176 : {'i', 'm', 'g', '\0'};
177 : static const PRUnichar sHTMLTagUnicodeName_input[] =
178 : {'i', 'n', 'p', 'u', 't', '\0'};
179 : static const PRUnichar sHTMLTagUnicodeName_ins[] =
180 : {'i', 'n', 's', '\0'};
181 : static const PRUnichar sHTMLTagUnicodeName_kbd[] =
182 : {'k', 'b', 'd', '\0'};
183 : static const PRUnichar sHTMLTagUnicodeName_keygen[] =
184 : {'k', 'e', 'y', 'g', 'e', 'n', '\0'};
185 : static const PRUnichar sHTMLTagUnicodeName_label[] =
186 : {'l', 'a', 'b', 'e', 'l', '\0'};
187 : static const PRUnichar sHTMLTagUnicodeName_legend[] =
188 : {'l', 'e', 'g', 'e', 'n', 'd', '\0'};
189 : static const PRUnichar sHTMLTagUnicodeName_li[] =
190 : {'l', 'i', '\0'};
191 : static const PRUnichar sHTMLTagUnicodeName_link[] =
192 : {'l', 'i', 'n', 'k', '\0'};
193 : static const PRUnichar sHTMLTagUnicodeName_listing[] =
194 : {'l', 'i', 's', 't', 'i', 'n', 'g', '\0'};
195 : static const PRUnichar sHTMLTagUnicodeName_map[] =
196 : {'m', 'a', 'p', '\0'};
197 : static const PRUnichar sHTMLTagUnicodeName_mark[] =
198 : {'m', 'a', 'r', 'k', '\0'};
199 : static const PRUnichar sHTMLTagUnicodeName_marquee[] =
200 : {'m', 'a', 'r', 'q', 'u', 'e', 'e', '\0'};
201 : static const PRUnichar sHTMLTagUnicodeName_menu[] =
202 : {'m', 'e', 'n', 'u', '\0'};
203 : static const PRUnichar sHTMLTagUnicodeName_menuitem[] =
204 : {'m', 'e', 'n', 'u', 'i', 't', 'e', 'm', '\0'};
205 : static const PRUnichar sHTMLTagUnicodeName_meta[] =
206 : {'m', 'e', 't', 'a', '\0'};
207 : static const PRUnichar sHTMLTagUnicodeName_multicol[] =
208 : {'m', 'u', 'l', 't', 'i', 'c', 'o', 'l', '\0'};
209 : static const PRUnichar sHTMLTagUnicodeName_nav[] =
210 : {'n', 'a', 'v', '\0'};
211 : static const PRUnichar sHTMLTagUnicodeName_nobr[] =
212 : {'n', 'o', 'b', 'r', '\0'};
213 : static const PRUnichar sHTMLTagUnicodeName_noembed[] =
214 : {'n', 'o', 'e', 'm', 'b', 'e', 'd', '\0'};
215 : static const PRUnichar sHTMLTagUnicodeName_noframes[] =
216 : {'n', 'o', 'f', 'r', 'a', 'm', 'e', 's', '\0'};
217 : static const PRUnichar sHTMLTagUnicodeName_noscript[] =
218 : {'n', 'o', 's', 'c', 'r', 'i', 'p', 't', '\0'};
219 : static const PRUnichar sHTMLTagUnicodeName_object[] =
220 : {'o', 'b', 'j', 'e', 'c', 't', '\0'};
221 : static const PRUnichar sHTMLTagUnicodeName_ol[] =
222 : {'o', 'l', '\0'};
223 : static const PRUnichar sHTMLTagUnicodeName_optgroup[] =
224 : {'o', 'p', 't', 'g', 'r', 'o', 'u', 'p', '\0'};
225 : static const PRUnichar sHTMLTagUnicodeName_option[] =
226 : {'o', 'p', 't', 'i', 'o', 'n', '\0'};
227 : static const PRUnichar sHTMLTagUnicodeName_output[] =
228 : {'o', 'u', 't', 'p', 'u', 't', '\0'};
229 : static const PRUnichar sHTMLTagUnicodeName_p[] =
230 : {'p', '\0'};
231 : static const PRUnichar sHTMLTagUnicodeName_param[] =
232 : {'p', 'a', 'r', 'a', 'm', '\0'};
233 : static const PRUnichar sHTMLTagUnicodeName_plaintext[] =
234 : {'p', 'l', 'a', 'i', 'n', 't', 'e', 'x', 't', '\0'};
235 : static const PRUnichar sHTMLTagUnicodeName_pre[] =
236 : {'p', 'r', 'e', '\0'};
237 : static const PRUnichar sHTMLTagUnicodeName_progress[] =
238 : {'p', 'r', 'o', 'g', 'r', 'e', 's', 's', '\0'};
239 : static const PRUnichar sHTMLTagUnicodeName_q[] =
240 : {'q', '\0'};
241 : static const PRUnichar sHTMLTagUnicodeName_s[] =
242 : {'s', '\0'};
243 : static const PRUnichar sHTMLTagUnicodeName_samp[] =
244 : {'s', 'a', 'm', 'p', '\0'};
245 : static const PRUnichar sHTMLTagUnicodeName_script[] =
246 : {'s', 'c', 'r', 'i', 'p', 't', '\0'};
247 : static const PRUnichar sHTMLTagUnicodeName_section[] =
248 : {'s', 'e', 'c', 't', 'i', 'o', 'n', '\0'};
249 : static const PRUnichar sHTMLTagUnicodeName_select[] =
250 : {'s', 'e', 'l', 'e', 'c', 't', '\0'};
251 : static const PRUnichar sHTMLTagUnicodeName_small[] =
252 : {'s', 'm', 'a', 'l', 'l', '\0'};
253 : #if defined(MOZ_MEDIA)
254 : static const PRUnichar sHTMLTagUnicodeName_source[] =
255 : {'s', 'o', 'u', 'r', 'c', 'e', '\0'};
256 : #endif
257 : static const PRUnichar sHTMLTagUnicodeName_spacer[] =
258 : {'s', 'p', 'a', 'c', 'e', 'r', '\0'};
259 : static const PRUnichar sHTMLTagUnicodeName_span[] =
260 : {'s', 'p', 'a', 'n', '\0'};
261 : static const PRUnichar sHTMLTagUnicodeName_strike[] =
262 : {'s', 't', 'r', 'i', 'k', 'e', '\0'};
263 : static const PRUnichar sHTMLTagUnicodeName_strong[] =
264 : {'s', 't', 'r', 'o', 'n', 'g', '\0'};
265 : static const PRUnichar sHTMLTagUnicodeName_style[] =
266 : {'s', 't', 'y', 'l', 'e', '\0'};
267 : static const PRUnichar sHTMLTagUnicodeName_sub[] =
268 : {'s', 'u', 'b', '\0'};
269 : static const PRUnichar sHTMLTagUnicodeName_sup[] =
270 : {'s', 'u', 'p', '\0'};
271 : static const PRUnichar sHTMLTagUnicodeName_table[] =
272 : {'t', 'a', 'b', 'l', 'e', '\0'};
273 : static const PRUnichar sHTMLTagUnicodeName_tbody[] =
274 : {'t', 'b', 'o', 'd', 'y', '\0'};
275 : static const PRUnichar sHTMLTagUnicodeName_td[] =
276 : {'t', 'd', '\0'};
277 : static const PRUnichar sHTMLTagUnicodeName_textarea[] =
278 : {'t', 'e', 'x', 't', 'a', 'r', 'e', 'a', '\0'};
279 : static const PRUnichar sHTMLTagUnicodeName_tfoot[] =
280 : {'t', 'f', 'o', 'o', 't', '\0'};
281 : static const PRUnichar sHTMLTagUnicodeName_th[] =
282 : {'t', 'h', '\0'};
283 : static const PRUnichar sHTMLTagUnicodeName_thead[] =
284 : {'t', 'h', 'e', 'a', 'd', '\0'};
285 : static const PRUnichar sHTMLTagUnicodeName_title[] =
286 : {'t', 'i', 't', 'l', 'e', '\0'};
287 : static const PRUnichar sHTMLTagUnicodeName_tr[] =
288 : {'t', 'r', '\0'};
289 : static const PRUnichar sHTMLTagUnicodeName_tt[] =
290 : {'t', 't', '\0'};
291 : static const PRUnichar sHTMLTagUnicodeName_u[] =
292 : {'u', '\0'};
293 : static const PRUnichar sHTMLTagUnicodeName_ul[] =
294 : {'u', 'l', '\0'};
295 : static const PRUnichar sHTMLTagUnicodeName_var[] =
296 : {'v', 'a', 'r', '\0'};
297 : #if defined(MOZ_MEDIA)
298 : static const PRUnichar sHTMLTagUnicodeName_video[] =
299 : {'v', 'i', 'd', 'e', 'o', '\0'};
300 : #endif
301 : static const PRUnichar sHTMLTagUnicodeName_wbr[] =
302 : {'w', 'b', 'r', '\0'};
303 : static const PRUnichar sHTMLTagUnicodeName_xmp[] =
304 : {'x', 'm', 'p', '\0'};
305 :
306 : // static array of unicode tag names
307 : #define HTML_TAG(_tag, _classname) sHTMLTagUnicodeName_##_tag,
308 : #define HTML_HTMLELEMENT_TAG(_tag) sHTMLTagUnicodeName_##_tag,
309 : #define HTML_OTHER(_tag)
310 : const PRUnichar* const nsHTMLTags::sTagUnicodeTable[] = {
311 : #include "nsHTMLTagList.h"
312 : };
313 : #undef HTML_TAG
314 : #undef HTML_HTMLELEMENT_TAG
315 : #undef HTML_OTHER
316 :
317 : // static array of tag atoms
318 : nsIAtom* nsHTMLTags::sTagAtomTable[eHTMLTag_userdefined - 1];
319 :
320 : PRInt32 nsHTMLTags::gTableRefCount;
321 : PLHashTable* nsHTMLTags::gTagTable;
322 : PLHashTable* nsHTMLTags::gTagAtomTable;
323 :
324 :
325 : // PRUnichar* -> id hash
326 : static PLHashNumber
327 128956 : HTMLTagsHashCodeUCPtr(const void *key)
328 : {
329 128956 : return HashString(static_cast<const PRUnichar*>(key));
330 : }
331 :
332 : static PRIntn
333 96607 : HTMLTagsKeyCompareUCPtr(const void *key1, const void *key2)
334 : {
335 96607 : const PRUnichar *str1 = (const PRUnichar *)key1;
336 96607 : const PRUnichar *str2 = (const PRUnichar *)key2;
337 :
338 96607 : return nsCRT::strcmp(str1, str2) == 0;
339 : }
340 :
341 : // nsIAtom* -> id hash
342 : static PLHashNumber
343 64973 : HTMLTagsHashCodeAtom(const void *key)
344 : {
345 64973 : return NS_PTR_TO_INT32(key) >> 2;
346 : }
347 :
348 : #define NS_HTMLTAG_NAME_MAX_LENGTH 10
349 :
350 : #define HTML_TAG(_tag, _classname) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
351 : #define HTML_HTMLELEMENT_TAG(_tag) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
352 : #define HTML_OTHER(_tag)
353 : #include "nsHTMLTagList.h"
354 : #undef HTML_TAG
355 : #undef HTML_HTMLELEMENT_TAG
356 : #undef HTML_OTHER
357 :
358 :
359 : // static
360 : nsresult
361 526 : nsHTMLTags::AddRefTable(void)
362 : {
363 : // static array of tag StaticAtom structs
364 : #define HTML_TAG(_tag, _classname) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
365 : #define HTML_HTMLELEMENT_TAG(_tag) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
366 : #define HTML_OTHER(_tag)
367 : static const nsStaticAtom sTagAtoms_info[] = {
368 : #include "nsHTMLTagList.h"
369 : };
370 : #undef HTML_TAG
371 : #undef HTML_HTMLELEMENT_TAG
372 : #undef HTML_OTHER
373 :
374 526 : if (gTableRefCount++ == 0) {
375 : // Fill in our static atom pointers
376 263 : NS_RegisterStaticAtoms(sTagAtoms_info);
377 :
378 :
379 263 : NS_ASSERTION(!gTagTable && !gTagAtomTable, "pre existing hash!");
380 :
381 : gTagTable = PL_NewHashTable(64, HTMLTagsHashCodeUCPtr,
382 : HTMLTagsKeyCompareUCPtr, PL_CompareValues,
383 263 : nsnull, nsnull);
384 263 : NS_ENSURE_TRUE(gTagTable, NS_ERROR_OUT_OF_MEMORY);
385 :
386 : gTagAtomTable = PL_NewHashTable(64, HTMLTagsHashCodeAtom,
387 : PL_CompareValues, PL_CompareValues,
388 263 : nsnull, nsnull);
389 263 : NS_ENSURE_TRUE(gTagAtomTable, NS_ERROR_OUT_OF_MEMORY);
390 :
391 : // Fill in gTagTable with the above static PRUnichar strings as
392 : // keys and the value of the corresponding enum as the value in
393 : // the table.
394 :
395 : PRInt32 i;
396 32086 : for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
397 31823 : PL_HashTableAdd(gTagTable, sTagUnicodeTable[i],
398 63646 : NS_INT32_TO_PTR(i + 1));
399 :
400 31823 : PL_HashTableAdd(gTagAtomTable, sTagAtomTable[i],
401 63646 : NS_INT32_TO_PTR(i + 1));
402 : }
403 :
404 :
405 :
406 : #if defined(DEBUG) && defined(NS_STATIC_ATOM_USE_WIDE_STRINGS)
407 : {
408 : // let's verify that all names in the the table are lowercase...
409 32086 : for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
410 63646 : nsAutoString temp1((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data());
411 63646 : nsAutoString temp2((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data());
412 31823 : ToLowerCase(temp1);
413 31823 : NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
414 : }
415 :
416 : // let's verify that all names in the unicode strings above are
417 : // correct.
418 32086 : for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
419 63646 : nsAutoString temp1(sTagUnicodeTable[i]);
420 63646 : nsAutoString temp2((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data());
421 31823 : NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!");
422 : }
423 :
424 : // let's verify that NS_HTMLTAG_NAME_MAX_LENGTH is correct
425 263 : PRUint32 maxTagNameLength = 0;
426 32086 : for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
427 31823 : PRUint32 len = nsCRT::strlen(sTagUnicodeTable[i]);
428 31823 : maxTagNameLength = NS_MAX(len, maxTagNameLength);
429 : }
430 263 : NS_ASSERTION(maxTagNameLength == NS_HTMLTAG_NAME_MAX_LENGTH,
431 : "NS_HTMLTAG_NAME_MAX_LENGTH not set correctly!");
432 : }
433 : #endif
434 : }
435 :
436 526 : return NS_OK;
437 : }
438 :
439 : // static
440 : void
441 526 : nsHTMLTags::ReleaseTable(void)
442 : {
443 526 : if (0 == --gTableRefCount) {
444 263 : if (gTagTable) {
445 : // Nothing to delete/free in this table, just destroy the table.
446 :
447 263 : PL_HashTableDestroy(gTagTable);
448 263 : PL_HashTableDestroy(gTagAtomTable);
449 263 : gTagTable = nsnull;
450 263 : gTagAtomTable = nsnull;
451 : }
452 : }
453 526 : }
454 :
455 : // static
456 : nsHTMLTag
457 65310 : nsHTMLTags::LookupTag(const nsAString& aTagName)
458 : {
459 65310 : PRUint32 length = aTagName.Length();
460 :
461 65310 : if (length > NS_HTMLTAG_NAME_MAX_LENGTH) {
462 0 : return eHTMLTag_userdefined;
463 : }
464 :
465 : PRUnichar buf[NS_HTMLTAG_NAME_MAX_LENGTH + 1];
466 :
467 65310 : nsAString::const_iterator iter;
468 65310 : PRUint32 i = 0;
469 : PRUnichar c;
470 :
471 65310 : aTagName.BeginReading(iter);
472 :
473 : // Fast lowercasing-while-copying of ASCII characters into a
474 : // PRUnichar buffer
475 :
476 425616 : while (i < length) {
477 294996 : c = *iter;
478 :
479 294996 : if (c <= 'Z' && c >= 'A') {
480 145798 : c |= 0x20; // Lowercase the ASCII character.
481 : }
482 :
483 294996 : buf[i] = c; // Copy ASCII character.
484 :
485 294996 : ++i;
486 294996 : ++iter;
487 : }
488 :
489 65310 : buf[i] = 0;
490 :
491 65310 : return CaseSensitiveLookupTag(buf);
492 : }
493 :
494 : #ifdef DEBUG
495 : void
496 263 : nsHTMLTags::TestTagTable()
497 : {
498 : const PRUnichar *tag;
499 : nsHTMLTag id;
500 526 : nsCOMPtr<nsIAtom> atom;
501 :
502 263 : nsHTMLTags::AddRefTable();
503 : // Make sure we can find everything we are supposed to
504 32086 : for (int i = 0; i < NS_HTML_TAG_MAX; ++i) {
505 31823 : tag = sTagUnicodeTable[i];
506 31823 : id = LookupTag(nsDependentString(tag));
507 31823 : NS_ASSERTION(id != eHTMLTag_userdefined, "can't find tag id");
508 31823 : const PRUnichar* check = GetStringValue(id);
509 31823 : NS_ASSERTION(0 == nsCRT::strcmp(check, tag), "can't map id back to tag");
510 :
511 63646 : nsAutoString uname(tag);
512 31823 : ToUpperCase(uname);
513 31823 : NS_ASSERTION(id == LookupTag(uname), "wrong id");
514 :
515 31823 : NS_ASSERTION(id == CaseSensitiveLookupTag(tag), "wrong id");
516 :
517 31823 : atom = do_GetAtom(tag);
518 31823 : NS_ASSERTION(id == CaseSensitiveLookupTag(atom), "wrong id");
519 31823 : NS_ASSERTION(atom == GetAtom(id), "can't map id back to atom");
520 : }
521 :
522 : // Make sure we don't find things that aren't there
523 263 : id = LookupTag(NS_LITERAL_STRING("@"));
524 263 : NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
525 263 : id = LookupTag(NS_LITERAL_STRING("zzzzz"));
526 263 : NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
527 :
528 263 : atom = do_GetAtom("@");
529 263 : id = CaseSensitiveLookupTag(atom);
530 263 : NS_ASSERTION(id == eHTMLTag_userdefined, "found @");
531 263 : atom = do_GetAtom("zzzzz");
532 263 : id = CaseSensitiveLookupTag(atom);
533 263 : NS_ASSERTION(id == eHTMLTag_userdefined, "found zzzzz");
534 :
535 263 : tag = GetStringValue((nsHTMLTag) 0);
536 263 : NS_ASSERTION(!tag, "found enum 0");
537 263 : tag = GetStringValue((nsHTMLTag) -1);
538 263 : NS_ASSERTION(!tag, "found enum -1");
539 263 : tag = GetStringValue((nsHTMLTag) (NS_HTML_TAG_MAX + 1));
540 263 : NS_ASSERTION(!tag, "found past max enum");
541 :
542 263 : atom = GetAtom((nsHTMLTag) 0);
543 263 : NS_ASSERTION(!atom, "found enum 0");
544 263 : atom = GetAtom((nsHTMLTag) -1);
545 263 : NS_ASSERTION(!atom, "found enum -1");
546 263 : atom = GetAtom((nsHTMLTag) (NS_HTML_TAG_MAX + 1));
547 263 : NS_ASSERTION(!atom, "found past max enum");
548 :
549 263 : ReleaseTable();
550 263 : }
551 :
552 : #endif // DEBUG
|