1 // Copyright 2017 PDFium Authors. All rights reserved.
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/ptr_util.h"
13
14 namespace {
15
GetCSSNameLen(const wchar_t * psz,const wchar_t * pEnd)16 int32_t GetCSSNameLen(const wchar_t* psz, const wchar_t* pEnd) {
17 const wchar_t* pStart = psz;
18 while (psz < pEnd) {
19 if (!isascii(*psz) || (!isalnum(*psz) && *psz != '_' && *psz != '-')) {
20 break;
21 }
22 ++psz;
23 }
24 return psz - pStart;
25 }
26
27 } // namespace
28
CFX_CSSSelector(CFX_CSSSelectorType eType,const wchar_t * psz,int32_t iLen,bool bIgnoreCase)29 CFX_CSSSelector::CFX_CSSSelector(CFX_CSSSelectorType eType,
30 const wchar_t* psz,
31 int32_t iLen,
32 bool bIgnoreCase)
33 : m_eType(eType),
34 m_dwHash(FX_HashCode_GetW(WideStringView(psz, iLen), bIgnoreCase)) {}
35
~CFX_CSSSelector()36 CFX_CSSSelector::~CFX_CSSSelector() {}
37
GetType() const38 CFX_CSSSelectorType CFX_CSSSelector::GetType() const {
39 return m_eType;
40 }
41
GetNameHash() const42 uint32_t CFX_CSSSelector::GetNameHash() const {
43 return m_dwHash;
44 }
45
GetNextSelector() const46 CFX_CSSSelector* CFX_CSSSelector::GetNextSelector() const {
47 return m_pNext.get();
48 }
49
50 // static.
FromString(WideStringView str)51 std::unique_ptr<CFX_CSSSelector> CFX_CSSSelector::FromString(
52 WideStringView str) {
53 ASSERT(!str.IsEmpty());
54
55 const wchar_t* psz = str.unterminated_c_str();
56 const wchar_t* pStart = psz;
57 const wchar_t* pEnd = psz + str.GetLength();
58 for (; psz < pEnd; ++psz) {
59 switch (*psz) {
60 case '>':
61 case '[':
62 case '+':
63 return nullptr;
64 }
65 }
66
67 std::unique_ptr<CFX_CSSSelector> pFirst = nullptr;
68 for (psz = pStart; psz < pEnd;) {
69 wchar_t wch = *psz;
70 if ((isascii(wch) && isalpha(wch)) || wch == '*') {
71 int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd);
72 auto p = pdfium::MakeUnique<CFX_CSSSelector>(CFX_CSSSelectorType::Element,
73 psz, iNameLen, true);
74 if (pFirst) {
75 pFirst->SetType(CFX_CSSSelectorType::Descendant);
76 p->SetNext(std::move(pFirst));
77 }
78 pFirst = std::move(p);
79 psz += iNameLen;
80 } else if (wch == ' ') {
81 psz++;
82 } else {
83 return nullptr;
84 }
85 }
86 return pFirst;
87 }
88