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 16 int32_t GetCSSNameLen(const wchar_t* psz, const wchar_t* pEnd) { 17 const wchar_t* pStart = psz; 18 while (psz < pEnd) { 19 wchar_t wch = *psz; 20 if (!FXSYS_iswalnum(wch) && wch != '_' && wch != '-') 21 break; 22 ++psz; 23 } 24 return psz - pStart; 25 } 26 27 } // namespace 28 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 36 CFX_CSSSelector::~CFX_CSSSelector() {} 37 38 CFX_CSSSelectorType CFX_CSSSelector::GetType() const { 39 return m_eType; 40 } 41 42 uint32_t CFX_CSSSelector::GetNameHash() const { 43 return m_dwHash; 44 } 45 46 CFX_CSSSelector* CFX_CSSSelector::GetNextSelector() const { 47 return m_pNext.get(); 48 } 49 50 // static. 51 std::unique_ptr<CFX_CSSSelector> CFX_CSSSelector::FromString( 52 const 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 (FXSYS_iswalpha(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