• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/css/cfx_cssselector.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/fx_extension.h"
12 #include "third_party/base/check.h"
13 
14 namespace {
15 
GetCSSNameLen(WideStringView str)16 size_t GetCSSNameLen(WideStringView str) {
17   for (size_t i = 0; i < str.GetLength(); ++i) {
18     wchar_t wch = str[i];
19     if (!isascii(wch) || (!isalnum(wch) && wch != '_' && wch != '-'))
20       return i;
21   }
22   return str.GetLength();
23 }
24 
25 }  // namespace
26 
CFX_CSSSelector(WideStringView str,std::unique_ptr<CFX_CSSSelector> next)27 CFX_CSSSelector::CFX_CSSSelector(WideStringView str,
28                                  std::unique_ptr<CFX_CSSSelector> next)
29     : name_hash_(FX_HashCode_GetLoweredW(str)), next_(std::move(next)) {}
30 
31 CFX_CSSSelector::~CFX_CSSSelector() = default;
32 
33 // static.
FromString(WideStringView str)34 std::unique_ptr<CFX_CSSSelector> CFX_CSSSelector::FromString(
35     WideStringView str) {
36   DCHECK(!str.IsEmpty());
37 
38   for (wchar_t wch : str) {
39     switch (wch) {
40       case '>':
41       case '[':
42       case '+':
43         return nullptr;
44     }
45   }
46 
47   std::unique_ptr<CFX_CSSSelector> head;
48   for (size_t i = 0; i < str.GetLength();) {
49     wchar_t wch = str[i];
50     if (wch == ' ') {
51       ++i;
52       continue;
53     }
54 
55     const bool is_star = wch == '*';
56     const bool is_valid_char = is_star || (isascii(wch) && isalpha(wch));
57     if (!is_valid_char)
58       return nullptr;
59 
60     if (head)
61       head->set_is_descendant();
62     size_t len = is_star ? 1 : GetCSSNameLen(str.Last(str.GetLength() - i));
63     auto new_head =
64         std::make_unique<CFX_CSSSelector>(str.Substr(i, len), std::move(head));
65     head = std::move(new_head);
66     i += len;
67   }
68   return head;
69 }
70