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 25573 2013-01-27 11:09:45Z rouault $");
41 :
42 : /************************************************************************/
43 : /* VSIPDFFileStream() */
44 : /************************************************************************/
45 :
46 149 : VSIPDFFileStream::VSIPDFFileStream(VSILFILE* f, const char* pszFilename, Object *dictA):
47 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
48 149 : BaseStream(dictA, 0)
49 : #else
50 : BaseStream(dictA)
51 : #endif
52 : {
53 149 : poParent = NULL;
54 149 : poFilename = new GooString(pszFilename);
55 149 : this->f = f;
56 149 : nStart = 0;
57 149 : bLimited = gFalse;
58 149 : nLength = 0;
59 149 : nCurrentPos = -1;
60 149 : bHasSavedPos = FALSE;
61 149 : nSavedPos = 0;
62 149 : nPosInBuffer = nBufferLength = -1;
63 149 : }
64 :
65 : /************************************************************************/
66 : /* VSIPDFFileStream() */
67 : /************************************************************************/
68 :
69 4604 : VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParent,
70 : vsi_l_offset startA, GBool limitedA,
71 : vsi_l_offset lengthA, Object *dictA):
72 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
73 4604 : BaseStream(dictA, lengthA)
74 : #else
75 : BaseStream(dictA)
76 : #endif
77 : {
78 4604 : this->poParent = poParent;
79 4604 : poFilename = poParent->poFilename;
80 4604 : f = poParent->f;
81 4604 : nStart = startA;
82 4604 : bLimited = limitedA;
83 4604 : nLength = lengthA;
84 4604 : nCurrentPos = -1;
85 4604 : bHasSavedPos = FALSE;
86 4604 : nSavedPos = 0;
87 4604 : nPosInBuffer = nBufferLength = -1;
88 4604 : }
89 :
90 : /************************************************************************/
91 : /* ~VSIPDFFileStream() */
92 : /************************************************************************/
93 :
94 4753 : VSIPDFFileStream::~VSIPDFFileStream()
95 : {
96 4753 : close();
97 4753 : if (poParent == NULL)
98 : {
99 149 : delete poFilename;
100 149 : if (f)
101 149 : VSIFCloseL(f);
102 : }
103 4753 : }
104 :
105 : /************************************************************************/
106 : /* copy() */
107 : /************************************************************************/
108 :
109 : #ifdef POPPLER_0_23_OR_LATER
110 0 : BaseStream* VSIPDFFileStream::copy()
111 : {
112 : return new VSIPDFFileStream(poParent, nStart, bLimited,
113 0 : nLength, &dict);
114 : }
115 : #endif
116 :
117 : /************************************************************************/
118 : /* makeSubStream() */
119 : /************************************************************************/
120 :
121 4604 : Stream *VSIPDFFileStream::makeSubStream(makeSubStream_offset_type startA, GBool limitedA,
122 : makeSubStream_offset_type lengthA, Object *dictA)
123 : {
124 : return new VSIPDFFileStream(this,
125 : startA, limitedA,
126 4604 : lengthA, dictA);
127 : }
128 :
129 : /************************************************************************/
130 : /* getPos() */
131 : /************************************************************************/
132 :
133 968 : getPos_ret_type VSIPDFFileStream::getPos()
134 : {
135 968 : return (getPos_ret_type) nCurrentPos;
136 : }
137 :
138 : /************************************************************************/
139 : /* getStart() */
140 : /************************************************************************/
141 :
142 :
143 149 : getStart_ret_type VSIPDFFileStream::getStart()
144 : {
145 149 : return (getStart_ret_type) nStart;
146 : }
147 :
148 : /************************************************************************/
149 : /* getKind() */
150 : /************************************************************************/
151 :
152 0 : StreamKind VSIPDFFileStream::getKind()
153 : {
154 0 : return strFile;
155 : }
156 :
157 : /************************************************************************/
158 : /* getFileName() */
159 : /************************************************************************/
160 :
161 298 : GooString *VSIPDFFileStream::getFileName()
162 : {
163 298 : return poFilename;
164 : }
165 :
166 : /************************************************************************/
167 : /* FillBuffer() */
168 : /************************************************************************/
169 :
170 9568 : int VSIPDFFileStream::FillBuffer()
171 : {
172 9568 : if (nBufferLength == 0)
173 0 : return FALSE;
174 9568 : if (nBufferLength != -1 && nBufferLength < BUFFER_SIZE)
175 74 : return FALSE;
176 :
177 9494 : nPosInBuffer = 0;
178 : int nToRead;
179 9494 : if (!bLimited)
180 4983 : nToRead = BUFFER_SIZE;
181 4511 : else if (nCurrentPos + BUFFER_SIZE > nStart + nLength)
182 630 : nToRead = (int)(nStart + nLength - nCurrentPos);
183 : else
184 3881 : nToRead = BUFFER_SIZE;
185 9494 : if( nToRead < 0 )
186 0 : return FALSE;
187 9494 : nBufferLength = (int) VSIFReadL(abyBuffer, 1, nToRead, f);
188 9494 : if (nBufferLength == 0)
189 0 : return FALSE;
190 :
191 9494 : return TRUE;
192 : }
193 :
194 : /************************************************************************/
195 : /* getChar() */
196 : /************************************************************************/
197 :
198 : /* The unoptimized version performs a bit well since we must go through */
199 : /* the whole virtual I/O chain for each character reading. We save a few */
200 : /* percent with this extra internal caching */
201 :
202 4973036 : int VSIPDFFileStream::getChar()
203 : {
204 : #ifdef unoptimized_version
205 : GByte chRead;
206 : if (bLimited && nCurrentPos >= nStart + nLength)
207 : return EOF;
208 : if (VSIFReadL(&chRead, 1, 1, f) == 0)
209 : return EOF;
210 : #else
211 4973036 : if (nPosInBuffer == nBufferLength)
212 : {
213 9568 : if (!FillBuffer() || nPosInBuffer >= nBufferLength)
214 74 : return EOF;
215 : }
216 :
217 4972962 : GByte chRead = abyBuffer[nPosInBuffer];
218 4972962 : nPosInBuffer ++;
219 : #endif
220 4972962 : nCurrentPos ++;
221 4972962 : return chRead;
222 : }
223 :
224 : /************************************************************************/
225 : /* getUnfilteredChar() */
226 : /************************************************************************/
227 :
228 0 : int VSIPDFFileStream::getUnfilteredChar ()
229 : {
230 0 : return getChar();
231 : }
232 :
233 : /************************************************************************/
234 : /* lookChar() */
235 : /************************************************************************/
236 :
237 0 : int VSIPDFFileStream::lookChar()
238 : {
239 : #ifdef unoptimized_version
240 : int nPosBefore = nCurrentPos;
241 : int chRead = getChar();
242 : if (chRead == EOF)
243 : return EOF;
244 : VSIFSeekL(f, nCurrentPos = nPosBefore, SEEK_SET);
245 : return chRead;
246 : #else
247 0 : int chRead = getChar();
248 0 : if (chRead == EOF)
249 0 : return EOF;
250 0 : nPosInBuffer --;
251 0 : nCurrentPos --;
252 0 : return chRead;
253 : #endif
254 : }
255 :
256 : /************************************************************************/
257 : /* reset() */
258 : /************************************************************************/
259 :
260 4736 : void VSIPDFFileStream::reset()
261 : {
262 4736 : nSavedPos = VSIFTellL(f);
263 4736 : bHasSavedPos = TRUE;
264 4736 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
265 4736 : nPosInBuffer = nBufferLength = -1;
266 4736 : }
267 :
268 : /************************************************************************/
269 : /* unfilteredReset() */
270 : /************************************************************************/
271 :
272 0 : void VSIPDFFileStream::unfilteredReset ()
273 : {
274 0 : reset();
275 0 : }
276 :
277 : /************************************************************************/
278 : /* close() */
279 : /************************************************************************/
280 :
281 8871 : void VSIPDFFileStream::close()
282 : {
283 8871 : if (bHasSavedPos)
284 4530 : VSIFSeekL(f, nCurrentPos = nSavedPos, SEEK_SET);
285 8871 : bHasSavedPos = FALSE;
286 8871 : nSavedPos = 0;
287 8871 : }
288 :
289 : /************************************************************************/
290 : /* setPos() */
291 : /************************************************************************/
292 :
293 967 : void VSIPDFFileStream::setPos(setPos_offset_type pos, int dir)
294 : {
295 967 : if (dir >= 0)
296 : {
297 669 : VSIFSeekL(f, nCurrentPos = pos, SEEK_SET);
298 : }
299 : else
300 : {
301 298 : if (bLimited == gFalse)
302 : {
303 298 : VSIFSeekL(f, 0, SEEK_END);
304 : }
305 : else
306 : {
307 0 : VSIFSeekL(f, nStart + nLength, SEEK_SET);
308 : }
309 298 : vsi_l_offset size = VSIFTellL(f);
310 298 : vsi_l_offset newpos = (vsi_l_offset) pos;
311 298 : if (newpos > size)
312 0 : newpos = size;
313 298 : VSIFSeekL(f, nCurrentPos = size - newpos, SEEK_SET);
314 : }
315 967 : nPosInBuffer = nBufferLength = -1;
316 967 : }
317 :
318 : /************************************************************************/
319 : /* moveStart() */
320 : /************************************************************************/
321 :
322 149 : void VSIPDFFileStream::moveStart(moveStart_delta_type delta)
323 : {
324 149 : nStart += delta;
325 149 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
326 149 : nPosInBuffer = nBufferLength = -1;
327 149 : }
328 :
329 : #endif
|