| // Copyright 2016 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 "core/fpdfapi/parser/cpdf_simple_parser.h" |
| |
| #include "core/fpdfapi/parser/fpdf_parser_utility.h" |
| |
| CPDF_SimpleParser::CPDF_SimpleParser(const uint8_t* pData, uint32_t dwSize) |
| : m_pData(pData), m_dwSize(dwSize), m_dwCurPos(0) {} |
| |
| CPDF_SimpleParser::CPDF_SimpleParser(const ByteStringView& str) |
| : m_pData(str.raw_str()), m_dwSize(str.GetLength()), m_dwCurPos(0) {} |
| |
| std::pair<const uint8_t*, uint32_t> CPDF_SimpleParser::ParseWord() { |
| const uint8_t* pStart = nullptr; |
| uint8_t dwSize = 0; |
| uint8_t ch; |
| while (1) { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| while (PDFCharIsWhitespace(ch)) { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| } |
| |
| if (ch != '%') |
| break; |
| |
| while (1) { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| if (PDFCharIsLineEnding(ch)) |
| break; |
| } |
| } |
| |
| uint32_t start_pos = m_dwCurPos - 1; |
| pStart = m_pData + start_pos; |
| if (PDFCharIsDelimiter(ch)) { |
| if (ch == '/') { |
| while (1) { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { |
| m_dwCurPos--; |
| dwSize = m_dwCurPos - start_pos; |
| return std::make_pair(pStart, dwSize); |
| } |
| } |
| } else { |
| dwSize = 1; |
| if (ch == '<') { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| if (ch == '<') |
| dwSize = 2; |
| else |
| m_dwCurPos--; |
| } else if (ch == '>') { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| if (ch == '>') |
| dwSize = 2; |
| else |
| m_dwCurPos--; |
| } |
| } |
| return std::make_pair(pStart, dwSize); |
| } |
| |
| dwSize = 1; |
| while (1) { |
| if (m_dwSize <= m_dwCurPos) |
| return std::make_pair(pStart, dwSize); |
| ch = m_pData[m_dwCurPos++]; |
| |
| if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { |
| m_dwCurPos--; |
| break; |
| } |
| dwSize++; |
| } |
| return std::make_pair(pStart, dwSize); |
| } |
| |
| ByteStringView CPDF_SimpleParser::GetWord() { |
| const uint8_t* pStart; |
| uint32_t dwSize; |
| std::tie(pStart, dwSize) = ParseWord(); |
| if (dwSize == 1 && pStart[0] == '<') { |
| while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') { |
| m_dwCurPos++; |
| } |
| if (m_dwCurPos < m_dwSize) { |
| m_dwCurPos++; |
| } |
| return ByteStringView(pStart, |
| static_cast<size_t>(m_dwCurPos - (pStart - m_pData))); |
| } |
| if (dwSize == 1 && pStart[0] == '(') { |
| int level = 1; |
| while (m_dwCurPos < m_dwSize) { |
| if (m_pData[m_dwCurPos] == ')') { |
| level--; |
| if (level == 0) { |
| break; |
| } |
| } |
| if (m_pData[m_dwCurPos] == '\\') { |
| if (m_dwSize <= m_dwCurPos) { |
| break; |
| } |
| m_dwCurPos++; |
| } else if (m_pData[m_dwCurPos] == '(') { |
| level++; |
| } |
| if (m_dwSize <= m_dwCurPos) { |
| break; |
| } |
| m_dwCurPos++; |
| } |
| if (m_dwCurPos < m_dwSize) { |
| m_dwCurPos++; |
| } |
| return ByteStringView(pStart, |
| static_cast<size_t>(m_dwCurPos - (pStart - m_pData))); |
| } |
| return ByteStringView(pStart, dwSize); |
| } |
| |
| bool CPDF_SimpleParser::FindTagParamFromStart(const ByteStringView& token, |
| int nParams) { |
| nParams++; |
| uint32_t* pBuf = FX_Alloc(uint32_t, nParams); |
| int buf_index = 0; |
| int buf_count = 0; |
| m_dwCurPos = 0; |
| while (1) { |
| pBuf[buf_index++] = m_dwCurPos; |
| if (buf_index == nParams) { |
| buf_index = 0; |
| } |
| buf_count++; |
| if (buf_count > nParams) { |
| buf_count = nParams; |
| } |
| ByteStringView word = GetWord(); |
| if (word.IsEmpty()) { |
| FX_Free(pBuf); |
| return false; |
| } |
| if (word == token) { |
| if (buf_count < nParams) { |
| continue; |
| } |
| m_dwCurPos = pBuf[buf_index]; |
| FX_Free(pBuf); |
| return true; |
| } |
| } |
| return false; |
| } |