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)15CFX_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()24CFX_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)70size_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)79size_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