| // Copyright 2017 The PDFium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "core/fxcrt/css/cfx_cssselector.h" |
| |
| #include <utility> |
| |
| #include "core/fxcrt/fx_extension.h" |
| #include "third_party/base/check.h" |
| |
| namespace { |
| |
| size_t GetCSSNameLen(WideStringView str) { |
| for (size_t i = 0; i < str.GetLength(); ++i) { |
| wchar_t wch = str[i]; |
| if (!isascii(wch) || (!isalnum(wch) && wch != '_' && wch != '-')) |
| return i; |
| } |
| return str.GetLength(); |
| } |
| |
| } // namespace |
| |
| CFX_CSSSelector::CFX_CSSSelector(WideStringView str, |
| std::unique_ptr<CFX_CSSSelector> next) |
| : name_hash_(FX_HashCode_GetLoweredW(str)), next_(std::move(next)) {} |
| |
| CFX_CSSSelector::~CFX_CSSSelector() = default; |
| |
| // static. |
| std::unique_ptr<CFX_CSSSelector> CFX_CSSSelector::FromString( |
| WideStringView str) { |
| DCHECK(!str.IsEmpty()); |
| |
| for (wchar_t wch : str) { |
| switch (wch) { |
| case '>': |
| case '[': |
| case '+': |
| return nullptr; |
| } |
| } |
| |
| std::unique_ptr<CFX_CSSSelector> head; |
| for (size_t i = 0; i < str.GetLength();) { |
| wchar_t wch = str[i]; |
| if (wch == ' ') { |
| ++i; |
| continue; |
| } |
| |
| const bool is_star = wch == '*'; |
| const bool is_valid_char = is_star || (isascii(wch) && isalpha(wch)); |
| if (!is_valid_char) |
| return nullptr; |
| |
| if (head) |
| head->set_is_descendant(); |
| size_t len = is_star ? 1 : GetCSSNameLen(str.Last(str.GetLength() - i)); |
| auto new_head = |
| std::make_unique<CFX_CSSSelector>(str.Substr(i, len), std::move(head)); |
| head = std::move(new_head); |
| i += len; |
| } |
| return head; |
| } |