1 // Copyright 2016 PDFium Authors. All rights reserved.
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/fpdfapi/parser/cpdf_simple_parser.h"
8
9 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
10
CPDF_SimpleParser(const uint8_t * pData,uint32_t dwSize)11 CPDF_SimpleParser::CPDF_SimpleParser(const uint8_t* pData, uint32_t dwSize)
12 : m_pData(pData), m_dwSize(dwSize), m_dwCurPos(0) {}
13
CPDF_SimpleParser(const ByteStringView & str)14 CPDF_SimpleParser::CPDF_SimpleParser(const ByteStringView& str)
15 : m_pData(str.raw_str()), m_dwSize(str.GetLength()), m_dwCurPos(0) {}
16
ParseWord()17 std::pair<const uint8_t*, uint32_t> CPDF_SimpleParser::ParseWord() {
18 const uint8_t* pStart = nullptr;
19 uint8_t dwSize = 0;
20 uint8_t ch;
21 while (1) {
22 if (m_dwSize <= m_dwCurPos)
23 return std::make_pair(pStart, dwSize);
24 ch = m_pData[m_dwCurPos++];
25 while (PDFCharIsWhitespace(ch)) {
26 if (m_dwSize <= m_dwCurPos)
27 return std::make_pair(pStart, dwSize);
28 ch = m_pData[m_dwCurPos++];
29 }
30
31 if (ch != '%')
32 break;
33
34 while (1) {
35 if (m_dwSize <= m_dwCurPos)
36 return std::make_pair(pStart, dwSize);
37 ch = m_pData[m_dwCurPos++];
38 if (PDFCharIsLineEnding(ch))
39 break;
40 }
41 }
42
43 uint32_t start_pos = m_dwCurPos - 1;
44 pStart = m_pData + start_pos;
45 if (PDFCharIsDelimiter(ch)) {
46 if (ch == '/') {
47 while (1) {
48 if (m_dwSize <= m_dwCurPos)
49 return std::make_pair(pStart, dwSize);
50 ch = m_pData[m_dwCurPos++];
51 if (!PDFCharIsOther(ch) && !PDFCharIsNumeric(ch)) {
52 m_dwCurPos--;
53 dwSize = m_dwCurPos - start_pos;
54 return std::make_pair(pStart, dwSize);
55 }
56 }
57 } else {
58 dwSize = 1;
59 if (ch == '<') {
60 if (m_dwSize <= m_dwCurPos)
61 return std::make_pair(pStart, dwSize);
62 ch = m_pData[m_dwCurPos++];
63 if (ch == '<')
64 dwSize = 2;
65 else
66 m_dwCurPos--;
67 } else if (ch == '>') {
68 if (m_dwSize <= m_dwCurPos)
69 return std::make_pair(pStart, dwSize);
70 ch = m_pData[m_dwCurPos++];
71 if (ch == '>')
72 dwSize = 2;
73 else
74 m_dwCurPos--;
75 }
76 }
77 return std::make_pair(pStart, dwSize);
78 }
79
80 dwSize = 1;
81 while (1) {
82 if (m_dwSize <= m_dwCurPos)
83 return std::make_pair(pStart, dwSize);
84 ch = m_pData[m_dwCurPos++];
85
86 if (PDFCharIsDelimiter(ch) || PDFCharIsWhitespace(ch)) {
87 m_dwCurPos--;
88 break;
89 }
90 dwSize++;
91 }
92 return std::make_pair(pStart, dwSize);
93 }
94
GetWord()95 ByteStringView CPDF_SimpleParser::GetWord() {
96 const uint8_t* pStart;
97 uint32_t dwSize;
98 std::tie(pStart, dwSize) = ParseWord();
99 if (dwSize == 1 && pStart[0] == '<') {
100 while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') {
101 m_dwCurPos++;
102 }
103 if (m_dwCurPos < m_dwSize) {
104 m_dwCurPos++;
105 }
106 return ByteStringView(pStart,
107 static_cast<size_t>(m_dwCurPos - (pStart - m_pData)));
108 }
109 if (dwSize == 1 && pStart[0] == '(') {
110 int level = 1;
111 while (m_dwCurPos < m_dwSize) {
112 if (m_pData[m_dwCurPos] == ')') {
113 level--;
114 if (level == 0) {
115 break;
116 }
117 }
118 if (m_pData[m_dwCurPos] == '\\') {
119 if (m_dwSize <= m_dwCurPos) {
120 break;
121 }
122 m_dwCurPos++;
123 } else if (m_pData[m_dwCurPos] == '(') {
124 level++;
125 }
126 if (m_dwSize <= m_dwCurPos) {
127 break;
128 }
129 m_dwCurPos++;
130 }
131 if (m_dwCurPos < m_dwSize) {
132 m_dwCurPos++;
133 }
134 return ByteStringView(pStart,
135 static_cast<size_t>(m_dwCurPos - (pStart - m_pData)));
136 }
137 return ByteStringView(pStart, dwSize);
138 }
139
FindTagParamFromStart(const ByteStringView & token,int nParams)140 bool CPDF_SimpleParser::FindTagParamFromStart(const ByteStringView& token,
141 int nParams) {
142 nParams++;
143 uint32_t* pBuf = FX_Alloc(uint32_t, nParams);
144 int buf_index = 0;
145 int buf_count = 0;
146 m_dwCurPos = 0;
147 while (1) {
148 pBuf[buf_index++] = m_dwCurPos;
149 if (buf_index == nParams) {
150 buf_index = 0;
151 }
152 buf_count++;
153 if (buf_count > nParams) {
154 buf_count = nParams;
155 }
156 ByteStringView word = GetWord();
157 if (word.IsEmpty()) {
158 FX_Free(pBuf);
159 return false;
160 }
161 if (word == token) {
162 if (buf_count < nParams) {
163 continue;
164 }
165 m_dwCurPos = pBuf[buf_index];
166 FX_Free(pBuf);
167 return true;
168 }
169 }
170 return false;
171 }
172