diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2017-01-19 10:27:58 -0500 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2017-01-19 15:49:07 +0000 |
commit | 95bec8046a28928df627ce4d48eee8b209b3e36e (patch) | |
tree | 46913cf24aacfc88a89bb55edcce8e3a2e724c4b /xfa/fde/css/cfde_csssyntaxparser.cpp | |
parent | dd533baad22f5143c093b98e98463a0dc62899ea (diff) | |
download | pdfium-95bec8046a28928df627ce4d48eee8b209b3e36e.tar.xz |
Split fde/css files into individual class files.
This CL splits the files in xfa/fde/css into class per file and renames any
needed files to match the class names.
Update some of the classes to use std::stack.
Change-Id: I4eca0fb3556d949a15a873bb0f0fd732f47e4fb1
Reviewed-on: https://pdfium-review.googlesource.com/2253
Commit-Queue: dsinclair <dsinclair@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Nicolás Peña <npm@chromium.org>
Diffstat (limited to 'xfa/fde/css/cfde_csssyntaxparser.cpp')
-rw-r--r-- | xfa/fde/css/cfde_csssyntaxparser.cpp | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/xfa/fde/css/cfde_csssyntaxparser.cpp b/xfa/fde/css/cfde_csssyntaxparser.cpp new file mode 100644 index 0000000000..a24b4eee66 --- /dev/null +++ b/xfa/fde/css/cfde_csssyntaxparser.cpp @@ -0,0 +1,380 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// 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 "xfa/fde/css/cfde_csssyntaxparser.h" + +#include <algorithm> + +#include "xfa/fde/css/cfde_cssdeclaration.h" +#include "xfa/fde/css/fde_cssdatatable.h" +#include "xfa/fgas/crt/fgas_codepage.h" + +namespace { + +bool IsSelectorStart(FX_WCHAR wch) { + return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') || + (wch >= 'A' && wch <= 'Z'); +} + +bool ParseCSSURI(const FX_WCHAR* pszValue, int32_t* iOffset, int32_t* iLength) { + ASSERT(pszValue && *iLength > 0); + if (*iLength < 6 || pszValue[*iLength - 1] != ')' || + FXSYS_wcsnicmp(L"url(", pszValue, 4)) { + return false; + } + if (CFDE_CSSDeclaration::ParseCSSString(pszValue + 4, *iLength - 5, iOffset, + iLength)) { + *iOffset += 4; + return true; + } + return false; +} + +} // namespace + +CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser() + : m_iTextDatLen(0), + m_dwCheck((uint32_t)-1), + m_eMode(FDE_CSSSyntaxMode::RuleSet), + m_eStatus(FDE_CSSSyntaxStatus::None) {} + +CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() { + m_TextData.Reset(); + m_TextPlane.Reset(); +} + +bool CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer, + int32_t iBufferSize, + int32_t iTextDatSize, + bool bOnlyDeclaration) { + ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0); + Reset(bOnlyDeclaration); + if (!m_TextData.EstimateSize(iTextDatSize)) + return false; + return m_TextPlane.AttachBuffer(pBuffer, iBufferSize); +} + +void CFDE_CSSSyntaxParser::Reset(bool bOnlyDeclaration) { + m_TextPlane.Reset(); + m_TextData.Reset(); + m_iTextDatLen = 0; + m_dwCheck = (uint32_t)-1; + m_eStatus = FDE_CSSSyntaxStatus::None; + m_eMode = bOnlyDeclaration ? FDE_CSSSyntaxMode::PropertyName + : FDE_CSSSyntaxMode::RuleSet; +} + +FDE_CSSSyntaxStatus CFDE_CSSSyntaxParser::DoSyntaxParse() { + while (m_eStatus >= FDE_CSSSyntaxStatus::None) { + if (m_TextPlane.IsEOF()) { + if (m_eMode == FDE_CSSSyntaxMode::PropertyValue && + m_TextData.GetLength() > 0) { + SaveTextData(); + m_eStatus = FDE_CSSSyntaxStatus::PropertyValue; + return m_eStatus; + } + m_eStatus = FDE_CSSSyntaxStatus::EOS; + return m_eStatus; + } + FX_WCHAR wch; + while (!m_TextPlane.IsEOF()) { + wch = m_TextPlane.GetChar(); + switch (m_eMode) { + case FDE_CSSSyntaxMode::RuleSet: + switch (wch) { + case '@': + m_TextPlane.MoveNext(); + SwitchMode(FDE_CSSSyntaxMode::AtRule); + break; + case '}': + m_TextPlane.MoveNext(); + if (RestoreMode()) + return FDE_CSSSyntaxStatus::DeclClose; + + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + m_ModeStack.push(m_eMode); + SwitchMode(FDE_CSSSyntaxMode::Comment); + break; + } + default: + if (wch <= ' ') { + m_TextPlane.MoveNext(); + } else if (IsSelectorStart(wch)) { + SwitchMode(FDE_CSSSyntaxMode::Selector); + return FDE_CSSSyntaxStatus::StyleRule; + } else { + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + } + break; + } + break; + case FDE_CSSSyntaxMode::Selector: + switch (wch) { + case ',': + m_TextPlane.MoveNext(); + SwitchMode(FDE_CSSSyntaxMode::Selector); + if (m_iTextDatLen > 0) + return FDE_CSSSyntaxStatus::Selector; + break; + case '{': + if (m_TextData.GetLength() > 0) { + SaveTextData(); + return FDE_CSSSyntaxStatus::Selector; + } + m_TextPlane.MoveNext(); + m_ModeStack.push(FDE_CSSSyntaxMode::RuleSet); + SwitchMode(FDE_CSSSyntaxMode::PropertyName); + return FDE_CSSSyntaxStatus::DeclOpen; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return FDE_CSSSyntaxStatus::Selector; + break; + } + default: + AppendChar(wch); + break; + } + break; + case FDE_CSSSyntaxMode::PropertyName: + switch (wch) { + case ':': + m_TextPlane.MoveNext(); + SwitchMode(FDE_CSSSyntaxMode::PropertyValue); + return FDE_CSSSyntaxStatus::PropertyName; + case '}': + m_TextPlane.MoveNext(); + if (RestoreMode()) + return FDE_CSSSyntaxStatus::DeclClose; + + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return FDE_CSSSyntaxStatus::PropertyName; + break; + } + default: + AppendChar(wch); + break; + } + break; + case FDE_CSSSyntaxMode::PropertyValue: + switch (wch) { + case ';': + m_TextPlane.MoveNext(); + case '}': + SwitchMode(FDE_CSSSyntaxMode::PropertyName); + return FDE_CSSSyntaxStatus::PropertyValue; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return FDE_CSSSyntaxStatus::PropertyValue; + break; + } + default: + AppendChar(wch); + break; + } + break; + case FDE_CSSSyntaxMode::Comment: + if (wch == '/' && m_TextData.GetLength() > 0 && + m_TextData.GetAt(m_TextData.GetLength() - 1) == '*') { + RestoreMode(); + } else { + m_TextData.AppendChar(wch); + } + m_TextPlane.MoveNext(); + break; + case FDE_CSSSyntaxMode::MediaType: + switch (wch) { + case ',': + m_TextPlane.MoveNext(); + SwitchMode(FDE_CSSSyntaxMode::MediaType); + if (m_iTextDatLen > 0) + return FDE_CSSSyntaxStatus::MediaType; + break; + case '{': { + if (m_ModeStack.empty() || + m_ModeStack.top() != FDE_CSSSyntaxMode::MediaRule) { + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + } + + if (m_TextData.GetLength() > 0) { + SaveTextData(); + return FDE_CSSSyntaxStatus::MediaType; + } + m_TextPlane.MoveNext(); + + // Replace the MediaRule with a RuleSet rule. + m_ModeStack.top() = FDE_CSSSyntaxMode::RuleSet; + + SwitchMode(FDE_CSSSyntaxMode::RuleSet); + return FDE_CSSSyntaxStatus::DeclOpen; + } + case ';': { + if (m_ModeStack.empty() || + m_ModeStack.top() != FDE_CSSSyntaxMode::Import) { + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + } + + if (m_TextData.GetLength() > 0) { + SaveTextData(); + if (IsImportEnabled()) + return FDE_CSSSyntaxStatus::MediaType; + } else { + bool bEnabled = IsImportEnabled(); + m_TextPlane.MoveNext(); + m_ModeStack.pop(); + SwitchMode(FDE_CSSSyntaxMode::RuleSet); + if (bEnabled) { + DisableImport(); + return FDE_CSSSyntaxStatus::ImportClose; + } + } + } break; + case '/': + if (m_TextPlane.GetNextChar() == '*') { + if (SwitchToComment() > 0) + return FDE_CSSSyntaxStatus::MediaType; + break; + } + default: + AppendChar(wch); + break; + } + break; + case FDE_CSSSyntaxMode::URI: { + if (m_ModeStack.empty() || + m_ModeStack.top() != FDE_CSSSyntaxMode::Import) { + m_eStatus = FDE_CSSSyntaxStatus::Error; + return m_eStatus; + } + + if (wch <= ' ' || wch == ';') { + int32_t iURIStart, iURILength = m_TextData.GetLength(); + if (iURILength > 0 && + ParseCSSURI(m_TextData.GetBuffer(), &iURIStart, &iURILength)) { + m_TextData.Subtract(iURIStart, iURILength); + SwitchMode(FDE_CSSSyntaxMode::MediaType); + if (IsImportEnabled()) + return FDE_CSSSyntaxStatus::URI; + break; + } + } + AppendChar(wch); + } break; + case FDE_CSSSyntaxMode::AtRule: + if (wch > ' ') { + AppendChar(wch); + } else { + int32_t iLen = m_TextData.GetLength(); + const FX_WCHAR* psz = m_TextData.GetBuffer(); + if (FXSYS_wcsncmp(L"charset", psz, iLen) == 0) { + SwitchMode(FDE_CSSSyntaxMode::Charset); + } else if (FXSYS_wcsncmp(L"import", psz, iLen) == 0) { + m_ModeStack.push(FDE_CSSSyntaxMode::Import); + SwitchMode(FDE_CSSSyntaxMode::URI); + if (IsImportEnabled()) + return FDE_CSSSyntaxStatus::ImportRule; + break; + } else if (FXSYS_wcsncmp(L"media", psz, iLen) == 0) { + m_ModeStack.push(FDE_CSSSyntaxMode::MediaRule); + SwitchMode(FDE_CSSSyntaxMode::MediaType); + return FDE_CSSSyntaxStatus::MediaRule; + } else if (FXSYS_wcsncmp(L"font-face", psz, iLen) == 0) { + SwitchMode(FDE_CSSSyntaxMode::Selector); + return FDE_CSSSyntaxStatus::FontFaceRule; + } else if (FXSYS_wcsncmp(L"page", psz, iLen) == 0) { + SwitchMode(FDE_CSSSyntaxMode::Selector); + return FDE_CSSSyntaxStatus::PageRule; + } else { + SwitchMode(FDE_CSSSyntaxMode::UnknownRule); + } + } + break; + case FDE_CSSSyntaxMode::Charset: + if (wch == ';') { + m_TextPlane.MoveNext(); + SwitchMode(FDE_CSSSyntaxMode::RuleSet); + if (IsCharsetEnabled()) { + DisableCharset(); + if (m_iTextDatLen > 0) + return FDE_CSSSyntaxStatus::Charset; + } + } else { + AppendChar(wch); + } + break; + case FDE_CSSSyntaxMode::UnknownRule: + if (wch == ';') + SwitchMode(FDE_CSSSyntaxMode::RuleSet); + m_TextPlane.MoveNext(); + break; + default: + ASSERT(false); + break; + } + } + } + return m_eStatus; +} + +bool CFDE_CSSSyntaxParser::IsImportEnabled() const { + if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) + return false; + if (m_ModeStack.size() > 1) + return false; + return true; +} + +bool CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) { + m_TextPlane.MoveNext(); + if (m_TextData.GetLength() > 0 || wch > ' ') { + m_TextData.AppendChar(wch); + return true; + } + return false; +} + +int32_t CFDE_CSSSyntaxParser::SaveTextData() { + m_iTextDatLen = m_TextData.TrimEnd(); + m_TextData.Clear(); + return m_iTextDatLen; +} + +void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSyntaxMode eMode) { + m_eMode = eMode; + SaveTextData(); +} + +int32_t CFDE_CSSSyntaxParser::SwitchToComment() { + int32_t iLength = m_TextData.GetLength(); + m_ModeStack.push(m_eMode); + SwitchMode(FDE_CSSSyntaxMode::Comment); + return iLength; +} + +bool CFDE_CSSSyntaxParser::RestoreMode() { + if (m_ModeStack.empty()) + return false; + + SwitchMode(m_ModeStack.top()); + m_ModeStack.pop(); + return true; +} + +const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const { + iLength = m_iTextDatLen; + return m_TextData.GetBuffer(); +} |