blob: 5358b183d899eb5f76dc2861ee012344b9847b3b [file] [log] [blame]
// 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) {}
void CPDF_SimpleParser::ParseWord(const uint8_t*& pStart, uint32_t& 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;
}
}
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;
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++;
}
}
ByteStringView CPDF_SimpleParser::GetWord() {
const uint8_t* pStart;
uint32_t 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 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;
}