// 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/fpdf_parser/include/cpdf_simple_parser.h" #include "core/fpdfapi/fpdf_parser/fpdf_parser_utility.h" CPDF_SimpleParser::CPDF_SimpleParser(const uint8_t* pData, FX_DWORD dwSize) : m_pData(pData), m_dwSize(dwSize), m_dwCurPos(0) {} CPDF_SimpleParser::CPDF_SimpleParser(const CFX_ByteStringC& str) : m_pData(str.GetPtr()), m_dwSize(str.GetLength()), m_dwCurPos(0) {} void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, FX_DWORD& dwSize) { pStart = nullptr; dwSize = 0; uint8_t ch; while (1) { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; while (PDFCharIsWhitespace(ch)) { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; } if (ch != '%') break; while (1) { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; if (PDFCharIsLineEnding(ch)) break; } } FX_DWORD start_pos = m_dwCurPos - 1; pStart = m_pData + start_pos; if (PDFCharIsDelimiter(ch)) { if (ch == '/') { while (1) { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) { m_dwCurPos--; dwSize = m_dwCurPos - start_pos; return; } } } else { dwSize = 1; if (ch == '<') { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; if (ch == '<') dwSize = 2; else m_dwCurPos--; } else if (ch == '>') { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; if (ch == '>') dwSize = 2; else m_dwCurPos--; } } return; } dwSize = 1; while (1) { if (m_dwSize <= m_dwCurPos) return; ch = m_pData[m_dwCurPos++]; if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) { m_dwCurPos--; break; } dwSize++; } } CFX_ByteStringC CPDF_SimpleParser::GetWord() { const uint8_t* pStart; FX_DWORD dwSize; ParseWord(pStart, dwSize); if (dwSize == 1 && pStart[0] == '<') { while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') { m_dwCurPos++; } if (m_dwCurPos < m_dwSize) { m_dwCurPos++; } return CFX_ByteStringC(pStart, (FX_STRSIZE)(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 CFX_ByteStringC(pStart, (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); } return CFX_ByteStringC(pStart, dwSize); } bool CPDF_SimpleParser::FindTagParamFromStart(const CFX_ByteStringC& token, int nParams) { nParams++; FX_DWORD* pBuf = FX_Alloc(FX_DWORD, 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; } CFX_ByteStringC 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; }