OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) |
3 * 1999 Waldo Bastian (bastian@kde.org) | 3 * 1999 Waldo Bastian (bastian@kde.org) |
4 * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) | 4 * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) |
5 * 2001-2003 Dirk Mueller (mueller@kde.org) | 5 * 2001-2003 Dirk Mueller (mueller@kde.org) |
6 * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv ed. | 6 * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv ed. |
7 * Copyright (C) 2008 David Smith (catfish.man@gmail.com) | 7 * Copyright (C) 2008 David Smith (catfish.man@gmail.com) |
8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/css/CSSSelector.h" | 27 #include "core/css/CSSSelector.h" |
28 | 28 |
29 #include "HTMLNames.h" | 29 #include "HTMLNames.h" |
30 #include "RuntimeEnabledFeatures.h" | 30 #include "RuntimeEnabledFeatures.h" |
31 #include "core/css/CSSOMUtils.h" | 31 #include "core/css/CSSOMUtils.h" |
32 #include "core/css/CSSSelectorList.h" | 32 #include "core/css/CSSSelectorList.h" |
33 #include "wtf/Assertions.h" | 33 #include "wtf/Assertions.h" |
34 #include "wtf/HashMap.h" | 34 #include "wtf/HashMap.h" |
35 #include "wtf/StdLibExtras.h" | 35 #include "wtf/StdLibExtras.h" |
36 #include "wtf/text/AtomicStringHash.h" | |
36 #include "wtf/text/StringBuilder.h" | 37 #include "wtf/text/StringBuilder.h" |
37 #include "wtf/text/StringHash.h" | |
38 | 38 |
39 #ifndef NDEBUG | 39 #ifndef NDEBUG |
40 #include <stdio.h> | 40 #include <stdio.h> |
41 #endif | 41 #endif |
42 | 42 |
43 namespace WebCore { | 43 namespace WebCore { |
44 | 44 |
45 using namespace HTMLNames; | 45 using namespace HTMLNames; |
46 | 46 |
47 struct SameSizeAsCSSSelector { | 47 struct SameSizeAsCSSSelector { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 ASSERT_NOT_REACHED(); | 267 ASSERT_NOT_REACHED(); |
268 return NOPSEUDO; | 268 return NOPSEUDO; |
269 } | 269 } |
270 | 270 |
271 // Could be made smaller and faster by replacing pointer with an | 271 // Could be made smaller and faster by replacing pointer with an |
272 // offset into a string buffer and making the bit fields smaller but | 272 // offset into a string buffer and making the bit fields smaller but |
273 // that could not be maintained by hand. | 273 // that could not be maintained by hand. |
274 struct NameToPseudoStruct { | 274 struct NameToPseudoStruct { |
275 const char* string; | 275 const char* string; |
276 unsigned type:8; | 276 unsigned type:8; |
277 | |
278 bool operator<(const NameToPseudoStruct& b) const { return strcmp(string, b. string) < 0; } | |
277 }; | 279 }; |
278 | 280 |
281 // This table should be kept sorted. | |
279 const static NameToPseudoStruct pseudoTypeMap[] = { | 282 const static NameToPseudoStruct pseudoTypeMap[] = { |
280 {"active", CSSSelector::PseudoActive}, | |
281 {"after", CSSSelector::PseudoAfter}, | |
282 {"-webkit-any(", CSSSelector::PseudoAny}, | 283 {"-webkit-any(", CSSSelector::PseudoAny}, |
283 {"-webkit-any-link", CSSSelector::PseudoAnyLink}, | 284 {"-webkit-any-link", CSSSelector::PseudoAnyLink}, |
284 {"-webkit-autofill", CSSSelector::PseudoAutofill}, | 285 {"-webkit-autofill", CSSSelector::PseudoAutofill}, |
285 {"backdrop", CSSSelector::PseudoBackdrop}, | |
286 {"before", CSSSelector::PseudoBefore}, | |
287 {"checked", CSSSelector::PseudoChecked}, | |
288 {"default", CSSSelector::PseudoDefault}, | |
289 {"disabled", CSSSelector::PseudoDisabled}, | |
290 {"read-only", CSSSelector::PseudoReadOnly}, | |
291 {"read-write", CSSSelector::PseudoReadWrite}, | |
292 {"valid", CSSSelector::PseudoValid}, | |
293 {"invalid", CSSSelector::PseudoInvalid}, | |
294 {"-webkit-drag", CSSSelector::PseudoDrag}, | 286 {"-webkit-drag", CSSSelector::PseudoDrag}, |
295 {"empty", CSSSelector::PseudoEmpty}, | |
296 {"enabled", CSSSelector::PseudoEnabled}, | |
297 {"first-child", CSSSelector::PseudoFirstChild}, | |
298 {"first-letter", CSSSelector::PseudoFirstLetter}, | |
299 {"first-line", CSSSelector::PseudoFirstLine}, | |
300 {"first-of-type", CSSSelector::PseudoFirstOfType}, | |
301 {"-webkit-full-page-media", CSSSelector::PseudoFullPageMedia}, | 287 {"-webkit-full-page-media", CSSSelector::PseudoFullPageMedia}, |
302 {"nth-child(", CSSSelector::PseudoNthChild}, | 288 {"-webkit-full-screen", CSSSelector::PseudoFullScreen}, |
303 {"nth-of-type(", CSSSelector::PseudoNthOfType}, | 289 {"-webkit-full-screen-ancestor", CSSSelector::PseudoFullScreenAncestor}, |
304 {"nth-last-child(", CSSSelector::PseudoNthLastChild}, | 290 {"-webkit-full-screen-document", CSSSelector::PseudoFullScreenDocument}, |
305 {"nth-last-of-type(", CSSSelector::PseudoNthLastOfType}, | |
306 {"focus", CSSSelector::PseudoFocus}, | |
307 {"hover", CSSSelector::PseudoHover}, | |
308 {"indeterminate", CSSSelector::PseudoIndeterminate}, | |
309 {"last-child", CSSSelector::PseudoLastChild}, | |
310 {"last-of-type", CSSSelector::PseudoLastOfType}, | |
311 {"link", CSSSelector::PseudoLink}, | |
312 {"lang(", CSSSelector::PseudoLang}, | |
313 {"not(", CSSSelector::PseudoNot}, | |
314 {"only-child", CSSSelector::PseudoOnlyChild}, | |
315 {"only-of-type", CSSSelector::PseudoOnlyOfType}, | |
316 {"optional", CSSSelector::PseudoOptional}, | |
317 {"required", CSSSelector::PseudoRequired}, | |
318 {"-webkit-resizer", CSSSelector::PseudoResizer}, | 291 {"-webkit-resizer", CSSSelector::PseudoResizer}, |
319 {"root", CSSSelector::PseudoRoot}, | |
320 {"-webkit-scrollbar", CSSSelector::PseudoScrollbar}, | 292 {"-webkit-scrollbar", CSSSelector::PseudoScrollbar}, |
321 {"-webkit-scrollbar-button", CSSSelector::PseudoScrollbarButton}, | 293 {"-webkit-scrollbar-button", CSSSelector::PseudoScrollbarButton}, |
322 {"-webkit-scrollbar-corner", CSSSelector::PseudoScrollbarCorner}, | 294 {"-webkit-scrollbar-corner", CSSSelector::PseudoScrollbarCorner}, |
323 {"-webkit-scrollbar-thumb", CSSSelector::PseudoScrollbarThumb}, | 295 {"-webkit-scrollbar-thumb", CSSSelector::PseudoScrollbarThumb}, |
324 {"-webkit-scrollbar-track", CSSSelector::PseudoScrollbarTrack}, | 296 {"-webkit-scrollbar-track", CSSSelector::PseudoScrollbarTrack}, |
325 {"-webkit-scrollbar-track-piece", CSSSelector::PseudoScrollbarTrackPiece}, | 297 {"-webkit-scrollbar-track-piece", CSSSelector::PseudoScrollbarTrackPiece}, |
326 {"selection", CSSSelector::PseudoSelection}, | 298 {"active", CSSSelector::PseudoActive}, |
327 {"target", CSSSelector::PseudoTarget}, | 299 {"after", CSSSelector::PseudoAfter}, |
328 {"visited", CSSSelector::PseudoVisited}, | 300 {"backdrop", CSSSelector::PseudoBackdrop}, |
329 {"window-inactive", CSSSelector::PseudoWindowInactive}, | 301 {"before", CSSSelector::PseudoBefore}, |
302 {"checked", CSSSelector::PseudoChecked}, | |
303 {"content", CSSSelector::PseudoContent}, | |
304 {"corner-present", CSSSelector::PseudoCornerPresent}, | |
305 {"cue", CSSSelector::PseudoWebKitCustomElement}, | |
306 {"cue(", CSSSelector::PseudoCue}, | |
330 {"decrement", CSSSelector::PseudoDecrement}, | 307 {"decrement", CSSSelector::PseudoDecrement}, |
331 {"increment", CSSSelector::PseudoIncrement}, | 308 {"default", CSSSelector::PseudoDefault}, |
332 {"start", CSSSelector::PseudoStart}, | 309 {"disabled", CSSSelector::PseudoDisabled}, |
310 {"double-button", CSSSelector::PseudoDoubleButton}, | |
311 {"empty", CSSSelector::PseudoEmpty}, | |
312 {"enabled", CSSSelector::PseudoEnabled}, | |
333 {"end", CSSSelector::PseudoEnd}, | 313 {"end", CSSSelector::PseudoEnd}, |
314 {"first", CSSSelector::PseudoFirstPage}, | |
315 {"first-child", CSSSelector::PseudoFirstChild}, | |
316 {"first-letter", CSSSelector::PseudoFirstLetter}, | |
317 {"first-line", CSSSelector::PseudoFirstLine}, | |
318 {"first-of-type", CSSSelector::PseudoFirstOfType}, | |
319 {"focus", CSSSelector::PseudoFocus}, | |
320 {"future", CSSSelector::PseudoFutureCue}, | |
334 {"horizontal", CSSSelector::PseudoHorizontal}, | 321 {"horizontal", CSSSelector::PseudoHorizontal}, |
335 {"vertical", CSSSelector::PseudoVertical}, | |
336 {"double-button", CSSSelector::PseudoDoubleButton}, | |
337 {"single-button", CSSSelector::PseudoSingleButton}, | |
338 {"no-button", CSSSelector::PseudoNoButton}, | |
339 {"corner-present", CSSSelector::PseudoCornerPresent}, | |
340 {"first", CSSSelector::PseudoFirstPage}, | |
341 {"left", CSSSelector::PseudoLeftPage}, | |
342 {"right", CSSSelector::PseudoRightPage}, | |
343 {"-webkit-full-screen", CSSSelector::PseudoFullScreen}, | |
344 {"-webkit-full-screen-document", CSSSelector::PseudoFullScreenDocument}, | |
345 {"-webkit-full-screen-ancestor", CSSSelector::PseudoFullScreenAncestor}, | |
346 {"cue(", CSSSelector::PseudoCue}, | |
347 {"cue", CSSSelector::PseudoWebKitCustomElement}, | |
348 {"future", CSSSelector::PseudoFutureCue}, | |
349 {"past", CSSSelector::PseudoPastCue}, | |
350 {"in-range", CSSSelector::PseudoInRange}, | |
351 {"out-of-range", CSSSelector::PseudoOutOfRange}, | |
352 {"scope", CSSSelector::PseudoScope}, | |
353 {"unresolved", CSSSelector::PseudoUnresolved}, | |
354 {"host", CSSSelector::PseudoHost}, | 322 {"host", CSSSelector::PseudoHost}, |
355 {"host(", CSSSelector::PseudoHost}, | 323 {"host(", CSSSelector::PseudoHost}, |
356 {"host-context(", CSSSelector::PseudoHostContext}, | 324 {"host-context(", CSSSelector::PseudoHostContext}, |
357 {"content", CSSSelector::PseudoContent}, | 325 {"hover", CSSSelector::PseudoHover}, |
326 {"in-range", CSSSelector::PseudoInRange}, | |
327 {"increment", CSSSelector::PseudoIncrement}, | |
328 {"indeterminate", CSSSelector::PseudoIndeterminate}, | |
329 {"invalid", CSSSelector::PseudoInvalid}, | |
330 {"lang(", CSSSelector::PseudoLang}, | |
331 {"last-child", CSSSelector::PseudoLastChild}, | |
332 {"last-of-type", CSSSelector::PseudoLastOfType}, | |
333 {"left", CSSSelector::PseudoLeftPage}, | |
334 {"link", CSSSelector::PseudoLink}, | |
335 {"no-button", CSSSelector::PseudoNoButton}, | |
336 {"not(", CSSSelector::PseudoNot}, | |
337 {"nth-child(", CSSSelector::PseudoNthChild}, | |
338 {"nth-last-child(", CSSSelector::PseudoNthLastChild}, | |
339 {"nth-last-of-type(", CSSSelector::PseudoNthLastOfType}, | |
340 {"nth-of-type(", CSSSelector::PseudoNthOfType}, | |
341 {"only-child", CSSSelector::PseudoOnlyChild}, | |
342 {"only-of-type", CSSSelector::PseudoOnlyOfType}, | |
343 {"optional", CSSSelector::PseudoOptional}, | |
344 {"out-of-range", CSSSelector::PseudoOutOfRange}, | |
345 {"past", CSSSelector::PseudoPastCue}, | |
346 {"read-only", CSSSelector::PseudoReadOnly}, | |
347 {"read-write", CSSSelector::PseudoReadWrite}, | |
348 {"required", CSSSelector::PseudoRequired}, | |
349 {"right", CSSSelector::PseudoRightPage}, | |
350 {"root", CSSSelector::PseudoRoot}, | |
351 {"scope", CSSSelector::PseudoScope}, | |
352 {"selection", CSSSelector::PseudoSelection}, | |
358 {"shadow", CSSSelector::PseudoShadow}, | 353 {"shadow", CSSSelector::PseudoShadow}, |
354 {"single-button", CSSSelector::PseudoSingleButton}, | |
355 {"start", CSSSelector::PseudoStart}, | |
356 {"target", CSSSelector::PseudoTarget}, | |
357 {"unresolved", CSSSelector::PseudoUnresolved}, | |
358 {"valid", CSSSelector::PseudoValid}, | |
359 {"vertical", CSSSelector::PseudoVertical}, | |
360 {"visited", CSSSelector::PseudoVisited}, | |
361 {"window-inactive", CSSSelector::PseudoWindowInactive}, | |
359 }; | 362 }; |
360 | 363 |
361 static HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap() | 364 static CSSSelector::PseudoType nameToPseudoType(const AtomicString& name) |
362 { | 365 { |
363 static HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0; | 366 typedef HashMap<AtomicString, CSSSelector::PseudoType> NameToPseudoTypeMap; |
364 if (!nameToPseudoType) { | 367 DEFINE_STATIC_LOCAL(NameToPseudoTypeMap, nameToPseudoTypeMap, ()); |
365 nameToPseudoType = new HashMap<StringImpl*, CSSSelector::PseudoType>; | |
366 | 368 |
367 size_t pseudoCount = WTF_ARRAY_LENGTH(pseudoTypeMap); | 369 NameToPseudoTypeMap::iterator slot = nameToPseudoTypeMap.find(name); |
esprehn
2014/04/25 09:08:03
You might even be able to always binary search and
fs
2014/04/25 11:23:33
Yepp, that's doable, but I figured it'd be too gna
| |
368 for (size_t i = 0; i < pseudoCount; i++) { | 370 if (slot != nameToPseudoTypeMap.end()) |
369 const char* str = pseudoTypeMap[i].string; | 371 return slot->value; |
370 CSSSelector::PseudoType type; | |
371 type = static_cast<CSSSelector::PseudoType>(pseudoTypeMap[i].type); | |
372 // This is a one-time leak. | |
373 AtomicString* name = new AtomicString(str, strlen(str), AtomicString ::ConstructFromLiteral); | |
374 nameToPseudoType->set(name->impl(), type); | |
375 } | |
376 } | |
377 | 372 |
378 return nameToPseudoType; | 373 const NameToPseudoStruct* pseudoTypeMapEnd = pseudoTypeMap + WTF_ARRAY_LENGT H(pseudoTypeMap); |
374 CString cstrName = name.utf8(); | |
apavlov
2014/04/24 15:19:18
This could as well be inlined
fs
2014/04/24 16:01:53
Assuming you by that mean:
... key = { name.utf8(
apavlov
2014/04/24 16:53:06
Ahh, correct. There's a newly constructed object i
| |
375 NameToPseudoStruct key = { cstrName.data(), CSSSelector::PseudoUnknown }; | |
376 const NameToPseudoStruct* match = std::lower_bound(pseudoTypeMap, pseudoType MapEnd, key); | |
377 if (match == pseudoTypeMapEnd || strcmp(match->string, key.string)) | |
378 return CSSSelector::PseudoUnknown; | |
379 | |
380 CSSSelector::PseudoType pseudoType = static_cast<CSSSelector::PseudoType>(ma tch->type); | |
381 nameToPseudoTypeMap.set(name, pseudoType); | |
382 return pseudoType; | |
379 } | 383 } |
380 | 384 |
381 #ifndef NDEBUG | 385 #ifndef NDEBUG |
382 void CSSSelector::show(int indent) const | 386 void CSSSelector::show(int indent) const |
383 { | 387 { |
384 printf("%*sselectorText(): %s\n", indent, "", selectorText().ascii().data()) ; | 388 printf("%*sselectorText(): %s\n", indent, "", selectorText().ascii().data()) ; |
385 printf("%*sm_match: %d\n", indent, "", m_match); | 389 printf("%*sm_match: %d\n", indent, "", m_match); |
386 printf("%*sisCustomPseudoElement(): %d\n", indent, "", isCustomPseudoElement ()); | 390 printf("%*sisCustomPseudoElement(): %d\n", indent, "", isCustomPseudoElement ()); |
387 if (m_match != Tag) | 391 if (m_match != Tag) |
388 printf("%*svalue(): %s\n", indent, "", value().ascii().data()); | 392 printf("%*svalue(): %s\n", indent, "", value().ascii().data()); |
(...skipping 18 matching lines...) Expand all Loading... | |
407 printf("\n******* CSSSelector::show(\"%s\") *******\n", selectorText().ascii ().data()); | 411 printf("\n******* CSSSelector::show(\"%s\") *******\n", selectorText().ascii ().data()); |
408 show(2); | 412 show(2); |
409 printf("******* end *******\n"); | 413 printf("******* end *******\n"); |
410 } | 414 } |
411 #endif | 415 #endif |
412 | 416 |
413 CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) | 417 CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) |
414 { | 418 { |
415 if (name.isNull()) | 419 if (name.isNull()) |
416 return PseudoUnknown; | 420 return PseudoUnknown; |
417 HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseu doTypeMap(); | |
418 HashMap<StringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoT ype->find(name.impl()); | |
419 | 421 |
420 if (slot != nameToPseudoType->end()) | 422 CSSSelector::PseudoType pseudoType = nameToPseudoType(name); |
421 return slot->value; | 423 if (pseudoType != PseudoUnknown) |
424 return pseudoType; | |
422 | 425 |
423 if (name.startsWith("-webkit-")) | 426 if (name.startsWith("-webkit-")) |
424 return PseudoWebKitCustomElement; | 427 return PseudoWebKitCustomElement; |
425 if (name.startsWith("cue")) | 428 if (name.startsWith("cue")) |
426 return PseudoUserAgentCustomElement; | 429 return PseudoUserAgentCustomElement; |
427 | 430 |
428 return PseudoUnknown; | 431 return PseudoUnknown; |
429 } | 432 } |
430 | 433 |
431 void CSSSelector::extractPseudoType() const | 434 void CSSSelector::extractPseudoType() const |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 return false; | 881 return false; |
879 return (count - m_b) % m_a == 0; | 882 return (count - m_b) % m_a == 0; |
880 } else { | 883 } else { |
881 if (count > m_b) | 884 if (count > m_b) |
882 return false; | 885 return false; |
883 return (m_b - count) % (-m_a) == 0; | 886 return (m_b - count) % (-m_a) == 0; |
884 } | 887 } |
885 } | 888 } |
886 | 889 |
887 } // namespace WebCore | 890 } // namespace WebCore |
OLD | NEW |