Chromium Code Reviews| 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 |