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/fx_extension.h"
10 #include "core/fxcrt/fx_system.h"
11 #include "third_party/base/check.h"
12 #include "third_party/base/check_op.h"
13
CFX_CSSValueListParser(const wchar_t * psz,size_t nLen,wchar_t separator)14 CFX_CSSValueListParser::CFX_CSSValueListParser(const wchar_t* psz,
15 size_t nLen,
16 wchar_t separator)
17 : m_Separator(separator), m_pCur(psz), m_pEnd(psz + nLen) {
18 DCHECK(psz);
19 DCHECK_NE(nLen, 0);
20 }
21
NextValue(CFX_CSSValue::PrimitiveType * eType,const wchar_t ** pStart,size_t * nLength)22 bool CFX_CSSValueListParser::NextValue(CFX_CSSValue::PrimitiveType* eType,
23 const wchar_t** pStart,
24 size_t* nLength) {
25 while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator))
26 ++m_pCur;
27
28 if (m_pCur >= m_pEnd)
29 return false;
30
31 *eType = CFX_CSSValue::PrimitiveType::kUnknown;
32 *pStart = m_pCur;
33 *nLength = 0;
34 wchar_t wch = *m_pCur;
35 if (wch == '#') {
36 *nLength = SkipToChar(' ');
37 if (*nLength == 4 || *nLength == 7)
38 *eType = CFX_CSSValue::PrimitiveType::kRGB;
39 } else if (FXSYS_IsDecimalDigit(wch) || wch == '.' || wch == '-' ||
40 wch == '+') {
41 while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator))
42 ++m_pCur;
43
44 *nLength = m_pCur - *pStart;
45 *eType = CFX_CSSValue::PrimitiveType::kNumber;
46 } else if (wch == '\"' || wch == '\'') {
47 ++(*pStart);
48 m_pCur++;
49 *nLength = SkipToChar(wch);
50 m_pCur++;
51 *eType = CFX_CSSValue::PrimitiveType::kString;
52 } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') {
53 if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) {
54 *nLength = SkipToChar(')') + 1;
55 m_pCur++;
56 *eType = CFX_CSSValue::PrimitiveType::kRGB;
57 }
58 } else {
59 *nLength = SkipToCharMatchingParens(m_Separator);
60 *eType = CFX_CSSValue::PrimitiveType::kString;
61 }
62 return m_pCur <= m_pEnd && *nLength > 0;
63 }
64
SkipToChar(wchar_t wch)65 size_t CFX_CSSValueListParser::SkipToChar(wchar_t wch) {
66 const wchar_t* pStart = m_pCur;
67 while (m_pCur < m_pEnd && *m_pCur != wch) {
68 m_pCur++;
69 }
70 return m_pCur - pStart;
71 }
72
SkipToCharMatchingParens(wchar_t wch)73 size_t CFX_CSSValueListParser::SkipToCharMatchingParens(wchar_t wch) {
74 const wchar_t* pStart = m_pCur;
75 int64_t bracketCount = 0;
76 while (m_pCur < m_pEnd && *m_pCur != wch) {
77 if (*m_pCur <= ' ')
78 break;
79 if (*m_pCur == '(')
80 bracketCount++;
81 else if (*m_pCur == ')')
82 bracketCount--;
83 m_pCur++;
84 }
85 while (bracketCount > 0 && m_pCur < m_pEnd) {
86 if (*m_pCur == ')')
87 bracketCount--;
88 m_pCur++;
89 }
90 return m_pCur - pStart;
91 }
92