Home | History | Annotate | Download | only in css
      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