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_cssvaluelistparser.h"
8
9CFDE_CSSValueListParser::CFDE_CSSValueListParser(const FX_WCHAR* psz,
10                                                 int32_t iLen,
11                                                 FX_WCHAR separator)
12    : m_Separator(separator), m_pCur(psz), m_pEnd(psz + iLen) {
13  ASSERT(psz && iLen > 0);
14}
15
16bool CFDE_CSSValueListParser::NextValue(FDE_CSSPrimitiveType& eType,
17                                        const FX_WCHAR*& pStart,
18                                        int32_t& iLength) {
19  while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator))
20    ++m_pCur;
21
22  if (m_pCur >= m_pEnd)
23    return false;
24
25  eType = FDE_CSSPrimitiveType::Unknown;
26  pStart = m_pCur;
27  iLength = 0;
28  FX_WCHAR wch = *m_pCur;
29  if (wch == '#') {
30    iLength = SkipTo(' ', false, false);
31    if (iLength == 4 || iLength == 7)
32      eType = FDE_CSSPrimitiveType::RGB;
33  } else if ((wch >= '0' && wch <= '9') || wch == '.' || wch == '-' ||
34             wch == '+') {
35    while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator))
36      ++m_pCur;
37
38    iLength = m_pCur - pStart;
39    eType = FDE_CSSPrimitiveType::Number;
40  } else if (wch == '\"' || wch == '\'') {
41    pStart++;
42    m_pCur++;
43    iLength = SkipTo(wch, false, false);
44    m_pCur++;
45    eType = FDE_CSSPrimitiveType::String;
46  } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') {
47    if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) {
48      iLength = SkipTo(')', false, false) + 1;
49      m_pCur++;
50      eType = FDE_CSSPrimitiveType::RGB;
51    }
52  } else {
53    iLength = SkipTo(m_Separator, true, true);
54    eType = FDE_CSSPrimitiveType::String;
55  }
56  return m_pCur <= m_pEnd && iLength > 0;
57}
58
59int32_t CFDE_CSSValueListParser::SkipTo(FX_WCHAR wch,
60                                        bool breakOnSpace,
61                                        bool matchBrackets) {
62  const FX_WCHAR* pStart = m_pCur;
63  int32_t bracketCount = 0;
64  while (m_pCur < m_pEnd && *m_pCur != wch) {
65    if (breakOnSpace && *m_pCur <= ' ')
66      break;
67    if (!matchBrackets) {
68      m_pCur++;
69      continue;
70    }
71
72    if (*m_pCur == '(')
73      bracketCount++;
74    else if (*m_pCur == ')')
75      bracketCount--;
76
77    m_pCur++;
78  }
79
80  while (bracketCount > 0 && m_pCur < m_pEnd) {
81    if (*m_pCur == ')')
82      bracketCount--;
83    m_pCur++;
84  }
85  return m_pCur - pStart;
86}
87