|  | // Copyright 2017 The PDFium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
|  |  | 
|  | #include "core/fxcrt/css/cfx_cssvaluelistparser.h" | 
|  |  | 
|  | #include "core/fxcrt/fx_extension.h" | 
|  | #include "core/fxcrt/fx_system.h" | 
|  | #include "third_party/base/check.h" | 
|  | #include "third_party/base/check_op.h" | 
|  |  | 
|  | CFX_CSSValueListParser::CFX_CSSValueListParser(const wchar_t* psz, | 
|  | size_t nLen, | 
|  | wchar_t separator) | 
|  | : m_Separator(separator), m_pCur(psz), m_pEnd(psz + nLen) { | 
|  | DCHECK(psz); | 
|  | DCHECK_NE(nLen, 0); | 
|  | } | 
|  |  | 
|  | bool CFX_CSSValueListParser::NextValue(CFX_CSSValue::PrimitiveType* eType, | 
|  | const wchar_t** pStart, | 
|  | size_t* nLength) { | 
|  | while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator)) | 
|  | ++m_pCur; | 
|  |  | 
|  | if (m_pCur >= m_pEnd) | 
|  | return false; | 
|  |  | 
|  | *eType = CFX_CSSValue::PrimitiveType::kUnknown; | 
|  | *pStart = m_pCur; | 
|  | *nLength = 0; | 
|  | wchar_t wch = *m_pCur; | 
|  | if (wch == '#') { | 
|  | *nLength = SkipToChar(' '); | 
|  | if (*nLength == 4 || *nLength == 7) | 
|  | *eType = CFX_CSSValue::PrimitiveType::kRGB; | 
|  | } else if (FXSYS_IsDecimalDigit(wch) || wch == '.' || wch == '-' || | 
|  | wch == '+') { | 
|  | while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator)) | 
|  | ++m_pCur; | 
|  |  | 
|  | *nLength = m_pCur - *pStart; | 
|  | *eType = CFX_CSSValue::PrimitiveType::kNumber; | 
|  | } else if (wch == '\"' || wch == '\'') { | 
|  | ++(*pStart); | 
|  | m_pCur++; | 
|  | *nLength = SkipToChar(wch); | 
|  | m_pCur++; | 
|  | *eType = CFX_CSSValue::PrimitiveType::kString; | 
|  | } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') { | 
|  | if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) { | 
|  | *nLength = SkipToChar(')') + 1; | 
|  | m_pCur++; | 
|  | *eType = CFX_CSSValue::PrimitiveType::kRGB; | 
|  | } | 
|  | } else { | 
|  | *nLength = SkipToCharMatchingParens(m_Separator); | 
|  | *eType = CFX_CSSValue::PrimitiveType::kString; | 
|  | } | 
|  | return m_pCur <= m_pEnd && *nLength > 0; | 
|  | } | 
|  |  | 
|  | size_t CFX_CSSValueListParser::SkipToChar(wchar_t wch) { | 
|  | const wchar_t* pStart = m_pCur; | 
|  | while (m_pCur < m_pEnd && *m_pCur != wch) { | 
|  | m_pCur++; | 
|  | } | 
|  | return m_pCur - pStart; | 
|  | } | 
|  |  | 
|  | size_t CFX_CSSValueListParser::SkipToCharMatchingParens(wchar_t wch) { | 
|  | const wchar_t* pStart = m_pCur; | 
|  | int64_t bracketCount = 0; | 
|  | while (m_pCur < m_pEnd && *m_pCur != wch) { | 
|  | if (*m_pCur <= ' ') | 
|  | break; | 
|  | if (*m_pCur == '(') | 
|  | bracketCount++; | 
|  | else if (*m_pCur == ')') | 
|  | bracketCount--; | 
|  | m_pCur++; | 
|  | } | 
|  | while (bracketCount > 0 && m_pCur < m_pEnd) { | 
|  | if (*m_pCur == ')') | 
|  | bracketCount--; | 
|  | m_pCur++; | 
|  | } | 
|  | return m_pCur - pStart; | 
|  | } |