1 : /******************************************************************************
2 : * $Id $
3 : *
4 : * Project: PDF driver
5 : * Purpose: GDALDataset driver for PDF dataset.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, Even Rouault
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #ifdef HAVE_POPPLER
31 :
32 : /* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
33 : /* in include/poppler/goo/gtypes.h with the one defined in cpl_port.h */
34 : #define CPL_GBOOL_DEFINED
35 :
36 : #include "pdfio.h"
37 :
38 : #include "cpl_vsi.h"
39 :
40 : CPL_CVSID("$Id: pdfio.cpp 24056 2012-03-03 19:04:22Z rouault $");
41 :
42 : /************************************************************************/
43 : /* VSIPDFFileStream() */
44 : /************************************************************************/
45 :
46 262 : VSIPDFFileStream::VSIPDFFileStream(VSILFILE* f, const char* pszFilename,
47 : Guint startA, GBool limitedA,
48 : Guint lengthA, Object *dictA):
49 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
50 262 : BaseStream(dictA, lengthA)
51 : #else
52 : BaseStream(dictA)
53 : #endif
54 : {
55 262 : poParent = NULL;
56 262 : poFilename = new GooString(pszFilename);
57 262 : this->f = f;
58 262 : nStart = startA;
59 262 : bLimited = limitedA;
60 262 : nLength = lengthA;
61 262 : nCurrentPos = -1;
62 262 : nSavedPos = -1;
63 262 : nPosInBuffer = nBufferLength = -1;
64 262 : }
65 :
66 : /************************************************************************/
67 : /* VSIPDFFileStream() */
68 : /************************************************************************/
69 :
70 5606 : VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParent,
71 : Guint startA, GBool limitedA,
72 : Guint lengthA, Object *dictA):
73 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
74 5606 : BaseStream(dictA, lengthA)
75 : #else
76 : BaseStream(dictA)
77 : #endif
78 : {
79 5606 : this->poParent = poParent;
80 5606 : poFilename = poParent->poFilename;
81 5606 : f = poParent->f;
82 5606 : nStart = startA;
83 5606 : bLimited = limitedA;
84 5606 : nLength = lengthA;
85 5606 : nCurrentPos = -1;
86 5606 : nSavedPos = -1;
87 5606 : nPosInBuffer = nBufferLength = -1;
88 5606 : }
89 :
90 : /************************************************************************/
91 : /* ~VSIPDFFileStream() */
92 : /************************************************************************/
93 :
94 5868 : VSIPDFFileStream::~VSIPDFFileStream()
95 : {
96 5868 : close();
97 5868 : if (poParent == NULL)
98 : {
99 262 : delete poFilename;
100 262 : if (f)
101 262 : VSIFCloseL(f);
102 : }
103 5868 : }
104 :
105 : /************************************************************************/
106 : /* makeSubStream() */
107 : /************************************************************************/
108 :
109 5606 : Stream *VSIPDFFileStream::makeSubStream(Guint startA, GBool limitedA,
110 : Guint lengthA, Object *dictA)
111 : {
112 : return new VSIPDFFileStream(this,
113 : startA, limitedA,
114 5606 : lengthA, dictA);
115 : }
116 :
117 : /************************************************************************/
118 : /* getPos() */
119 : /************************************************************************/
120 :
121 1022 : int VSIPDFFileStream::getPos()
122 : {
123 1022 : return nCurrentPos;
124 : }
125 :
126 : /************************************************************************/
127 : /* getStart() */
128 : /************************************************************************/
129 :
130 262 : Guint VSIPDFFileStream::getStart()
131 : {
132 262 : return nStart;
133 : }
134 :
135 : /************************************************************************/
136 : /* getKind() */
137 : /************************************************************************/
138 :
139 0 : StreamKind VSIPDFFileStream::getKind()
140 : {
141 0 : return strFile;
142 : }
143 :
144 : /************************************************************************/
145 : /* getFileName() */
146 : /************************************************************************/
147 :
148 524 : GooString *VSIPDFFileStream::getFileName()
149 : {
150 524 : return poFilename;
151 : }
152 :
153 : /************************************************************************/
154 : /* FillBuffer() */
155 : /************************************************************************/
156 :
157 16922 : int VSIPDFFileStream::FillBuffer()
158 : {
159 16922 : if (nBufferLength == 0)
160 0 : return FALSE;
161 16922 : if (nBufferLength != -1 && nBufferLength < BUFFER_SIZE)
162 112 : return FALSE;
163 :
164 16810 : nPosInBuffer = 0;
165 : int nToRead;
166 16810 : if (!bLimited)
167 6278 : nToRead = BUFFER_SIZE;
168 10532 : else if (nCurrentPos + BUFFER_SIZE > nStart + nLength)
169 376 : nToRead = nStart + nLength - nCurrentPos;
170 : else
171 10156 : nToRead = BUFFER_SIZE;
172 16810 : nBufferLength = VSIFReadL(abyBuffer, 1, nToRead, f);
173 16810 : if (nBufferLength == 0)
174 0 : return FALSE;
175 :
176 16810 : return TRUE;
177 : }
178 :
179 : /************************************************************************/
180 : /* getChar() */
181 : /************************************************************************/
182 :
183 : /* The unoptimized version performs a bit well since we must go through */
184 : /* the whole virtual I/O chain for each character reading. We save a few */
185 : /* percent with this extra internal caching */
186 :
187 11936052 : int VSIPDFFileStream::getChar()
188 : {
189 : #ifdef unoptimized_version
190 : GByte chRead;
191 : if (bLimited && nCurrentPos >= nStart + nLength)
192 : return EOF;
193 : if (VSIFReadL(&chRead, 1, 1, f) == 0)
194 : return EOF;
195 : #else
196 11936052 : if (nPosInBuffer == nBufferLength)
197 : {
198 16922 : if (!FillBuffer() || nPosInBuffer >= nBufferLength)
199 112 : return EOF;
200 : }
201 :
202 11935940 : GByte chRead = abyBuffer[nPosInBuffer];
203 11935940 : nPosInBuffer ++;
204 : #endif
205 11935940 : nCurrentPos ++;
206 11935940 : return chRead;
207 : }
208 :
209 : /************************************************************************/
210 : /* getUnfilteredChar() */
211 : /************************************************************************/
212 :
213 0 : int VSIPDFFileStream::getUnfilteredChar ()
214 : {
215 0 : return getChar();
216 : }
217 :
218 : /************************************************************************/
219 : /* lookChar() */
220 : /************************************************************************/
221 :
222 0 : int VSIPDFFileStream::lookChar()
223 : {
224 : #ifdef unoptimized_version
225 : int nPosBefore = nCurrentPos;
226 : int chRead = getChar();
227 : if (chRead == EOF)
228 : return EOF;
229 : VSIFSeekL(f, nCurrentPos = nPosBefore, SEEK_SET);
230 : return chRead;
231 : #else
232 0 : int chRead = getChar();
233 0 : if (chRead == EOF)
234 0 : return EOF;
235 0 : nPosInBuffer --;
236 0 : nCurrentPos --;
237 0 : return chRead;
238 : #endif
239 : }
240 :
241 : /************************************************************************/
242 : /* reset() */
243 : /************************************************************************/
244 :
245 5828 : void VSIPDFFileStream::reset()
246 : {
247 5828 : nSavedPos = (int)VSIFTellL(f);
248 5828 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
249 5828 : nPosInBuffer = nBufferLength = -1;
250 5828 : }
251 :
252 : /************************************************************************/
253 : /* unfilteredReset() */
254 : /************************************************************************/
255 :
256 0 : void VSIPDFFileStream::unfilteredReset ()
257 : {
258 0 : reset();
259 0 : }
260 :
261 : /************************************************************************/
262 : /* close() */
263 : /************************************************************************/
264 :
265 11406 : void VSIPDFFileStream::close()
266 : {
267 11406 : if (nSavedPos != -1)
268 5804 : VSIFSeekL(f, nCurrentPos = nSavedPos, SEEK_SET);
269 11406 : nSavedPos = -1;
270 11406 : }
271 :
272 : /************************************************************************/
273 : /* setPos() */
274 : /************************************************************************/
275 :
276 984 : void VSIPDFFileStream::setPos(Guint pos, int dir)
277 : {
278 984 : if (dir >= 0)
279 : {
280 460 : VSIFSeekL(f, nCurrentPos = pos, SEEK_SET);
281 : }
282 : else
283 : {
284 524 : if (bLimited == gFalse)
285 : {
286 524 : VSIFSeekL(f, 0, SEEK_END);
287 : }
288 : else
289 : {
290 0 : VSIFSeekL(f, nStart + nLength, SEEK_SET);
291 : }
292 524 : Guint size = (Guint)VSIFTellL(f);
293 524 : if (pos > size)
294 0 : pos = (Guint)size;
295 524 : VSIFSeekL(f, nCurrentPos = size - pos, SEEK_SET);
296 : }
297 984 : nPosInBuffer = nBufferLength = -1;
298 984 : }
299 :
300 : /************************************************************************/
301 : /* moveStart() */
302 : /************************************************************************/
303 :
304 262 : void VSIPDFFileStream::moveStart(int delta)
305 : {
306 262 : nStart += delta;
307 262 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
308 262 : nPosInBuffer = nBufferLength = -1;
309 262 : }
310 :
311 : #endif
|