• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The PDFium Authors
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_cssvaluelistparser.h"
8 
9 #include "core/fxcrt/check.h"
10 #include "core/fxcrt/check_op.h"
11 #include "core/fxcrt/compiler_specific.h"
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/fx_system.h"
14 
CFX_CSSValueListParser(WideStringView list,wchar_t separator)15 CFX_CSSValueListParser::CFX_CSSValueListParser(WideStringView list,
16                                                wchar_t separator)
17     : m_Cur(list), m_Separator(separator) {
18   DCHECK(CharsRemain());
19 }
20 
21 CFX_CSSValueListParser::~CFX_CSSValueListParser() = default;
22 
23 std::optional<CFX_CSSValueListParser::Result>
NextValue()24 CFX_CSSValueListParser::NextValue() {
25   while (CharsRemain() &&
26          (CurrentChar() <= ' ' || CurrentChar() == m_Separator)) {
27     Advance();
28   }
29   if (!CharsRemain()) {
30     return std::nullopt;
31   }
32   auto eType = CFX_CSSValue::PrimitiveType::kUnknown;
33   WideStringView start = m_Cur;
34   size_t nLength = 0;
35   wchar_t wch = CurrentChar();
36   if (wch == '#') {
37     nLength = SkipToChar(' ');
38     if (nLength == 4 || nLength == 7) {
39       eType = CFX_CSSValue::PrimitiveType::kRGB;
40     }
41   } else if (FXSYS_IsDecimalDigit(wch) || wch == '.' || wch == '-' ||
42              wch == '+') {
43     while (CharsRemain() &&
44            (CurrentChar() > ' ' && CurrentChar() != m_Separator)) {
45       ++nLength;
46       Advance();
47     }
48     eType = CFX_CSSValue::PrimitiveType::kNumber;
49   } else if (wch == '\"' || wch == '\'') {
50     start = start.Substr(1);
51     Advance();
52     nLength = SkipToChar(wch);
53     Advance();
54     eType = CFX_CSSValue::PrimitiveType::kString;
55   } else if (m_Cur.First(4).EqualsASCIINoCase(
56                  "rgb(")) {  // First() always safe.
57     nLength = SkipToChar(')') + 1;
58     Advance();
59     eType = CFX_CSSValue::PrimitiveType::kRGB;
60   } else {
61     nLength = SkipToCharMatchingParens(m_Separator);
62     eType = CFX_CSSValue::PrimitiveType::kString;
63   }
64   if (nLength == 0) {
65     return std::nullopt;
66   }
67   return Result{eType, start.First(nLength)};
68 }
69 
SkipToChar(wchar_t wch)70 size_t CFX_CSSValueListParser::SkipToChar(wchar_t wch) {
71   size_t count = 0;
72   while (CharsRemain() && CurrentChar() != wch) {
73     Advance();
74     ++count;
75   }
76   return count;
77 }
78 
SkipToCharMatchingParens(wchar_t wch)79 size_t CFX_CSSValueListParser::SkipToCharMatchingParens(wchar_t wch) {
80   size_t nLength = 0;
81   int64_t bracketCount = 0;
82   while (CharsRemain() && CurrentChar() != wch) {
83     if (CurrentChar() <= ' ') {
84       break;
85     }
86     if (CurrentChar() == '(') {
87       bracketCount++;
88     } else if (CurrentChar() == ')') {
89       bracketCount--;
90     }
91     ++nLength;
92     Advance();
93   }
94   while (bracketCount > 0 && CharsRemain()) {
95     if (CurrentChar() == ')') {
96       bracketCount--;
97     }
98     ++nLength;
99     Advance();
100   }
101   return nLength;
102 }
103