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