xref: /aosp_15_r20/external/pdfium/core/fxcrt/css/cfx_cssvaluelistparser.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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