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 "xfa/fde/css/cfde_cssselector.h" 8 9 #include <utility> 10 11 #include "third_party/base/ptr_util.h" 12 13 namespace { 14 15 bool IsCSSChar(FX_WCHAR wch) { 16 return (wch >= 'a' && wch <= 'z') || (wch >= 'A' && wch <= 'Z'); 17 } 18 19 int32_t GetCSSNameLen(const FX_WCHAR* psz, const FX_WCHAR* pEnd) { 20 const FX_WCHAR* pStart = psz; 21 while (psz < pEnd) { 22 FX_WCHAR wch = *psz; 23 if (IsCSSChar(wch) || (wch >= '0' && wch <= '9') || wch == '_' || 24 wch == '-') { 25 ++psz; 26 } else { 27 break; 28 } 29 } 30 return psz - pStart; 31 } 32 33 } // namespace 34 35 CFDE_CSSSelector::CFDE_CSSSelector(FDE_CSSSelectorType eType, 36 const FX_WCHAR* psz, 37 int32_t iLen, 38 bool bIgnoreCase) 39 : m_eType(eType), 40 m_dwHash(FX_HashCode_GetW(CFX_WideStringC(psz, iLen), bIgnoreCase)) {} 41 42 CFDE_CSSSelector::~CFDE_CSSSelector() {} 43 44 FDE_CSSSelectorType CFDE_CSSSelector::GetType() const { 45 return m_eType; 46 } 47 48 uint32_t CFDE_CSSSelector::GetNameHash() const { 49 return m_dwHash; 50 } 51 52 CFDE_CSSSelector* CFDE_CSSSelector::GetNextSelector() const { 53 return m_pNext.get(); 54 } 55 56 // static. 57 std::unique_ptr<CFDE_CSSSelector> CFDE_CSSSelector::FromString( 58 const CFX_WideStringC& str) { 59 ASSERT(!str.IsEmpty()); 60 61 const FX_WCHAR* psz = str.c_str(); 62 const FX_WCHAR* pStart = psz; 63 const FX_WCHAR* pEnd = psz + str.GetLength(); 64 for (; psz < pEnd; ++psz) { 65 switch (*psz) { 66 case '>': 67 case '[': 68 case '+': 69 return nullptr; 70 } 71 } 72 73 std::unique_ptr<CFDE_CSSSelector> pFirst = nullptr; 74 for (psz = pStart; psz < pEnd;) { 75 FX_WCHAR wch = *psz; 76 if (IsCSSChar(wch) || wch == '*') { 77 int32_t iNameLen = wch == '*' ? 1 : GetCSSNameLen(psz, pEnd); 78 auto p = pdfium::MakeUnique<CFDE_CSSSelector>( 79 FDE_CSSSelectorType::Element, psz, iNameLen, true); 80 if (pFirst) { 81 pFirst->SetType(FDE_CSSSelectorType::Descendant); 82 p->SetNext(std::move(pFirst)); 83 } 84 pFirst = std::move(p); 85 psz += iNameLen; 86 } else if (wch == ' ') { 87 psz++; 88 } else { 89 return nullptr; 90 } 91 } 92 return pFirst; 93 } 94