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 146 : 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 146 : BaseStream(dictA, lengthA)
51 : #else
52 : BaseStream(dictA)
53 : #endif
54 : {
55 146 : poParent = NULL;
56 146 : poFilename = new GooString(pszFilename);
57 146 : this->f = f;
58 146 : nStart = startA;
59 146 : bLimited = limitedA;
60 146 : nLength = lengthA;
61 146 : nCurrentPos = -1;
62 146 : nSavedPos = -1;
63 146 : nPosInBuffer = nBufferLength = -1;
64 146 : }
65 :
66 : /************************************************************************/
67 : /* VSIPDFFileStream() */
68 : /************************************************************************/
69 :
70 4454 : VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParent,
71 : Guint startA, GBool limitedA,
72 : Guint lengthA, Object *dictA):
73 : #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
74 4454 : BaseStream(dictA, lengthA)
75 : #else
76 : BaseStream(dictA)
77 : #endif
78 : {
79 4454 : this->poParent = poParent;
80 4454 : poFilename = poParent->poFilename;
81 4454 : f = poParent->f;
82 4454 : nStart = startA;
83 4454 : bLimited = limitedA;
84 4454 : nLength = lengthA;
85 4454 : nCurrentPos = -1;
86 4454 : nSavedPos = -1;
87 4454 : nPosInBuffer = nBufferLength = -1;
88 4454 : }
89 :
90 : /************************************************************************/
91 : /* ~VSIPDFFileStream() */
92 : /************************************************************************/
93 :
94 4600 : VSIPDFFileStream::~VSIPDFFileStream()
95 : {
96 4600 : close();
97 4600 : if (poParent == NULL)
98 : {
99 146 : delete poFilename;
100 146 : if (f)
101 146 : VSIFCloseL(f);
102 : }
103 4600 : }
104 :
105 : /************************************************************************/
106 : /* makeSubStream() */
107 : /************************************************************************/
108 :
109 4454 : Stream *VSIPDFFileStream::makeSubStream(Guint startA, GBool limitedA,
110 : Guint lengthA, Object *dictA)
111 : {
112 : return new VSIPDFFileStream(this,
113 : startA, limitedA,
114 4454 : lengthA, dictA);
115 : }
116 :
117 : /************************************************************************/
118 : /* getPos() */
119 : /************************************************************************/
120 :
121 941 : int VSIPDFFileStream::getPos()
122 : {
123 941 : return nCurrentPos;
124 : }
125 :
126 : /************************************************************************/
127 : /* getStart() */
128 : /************************************************************************/
129 :
130 146 : Guint VSIPDFFileStream::getStart()
131 : {
132 146 : 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 292 : GooString *VSIPDFFileStream::getFileName()
149 : {
150 292 : return poFilename;
151 : }
152 :
153 : /************************************************************************/
154 : /* FillBuffer() */
155 : /************************************************************************/
156 :
157 9388 : int VSIPDFFileStream::FillBuffer()
158 : {
159 9388 : if (nBufferLength == 0)
160 0 : return FALSE;
161 9388 : if (nBufferLength != -1 && nBufferLength < BUFFER_SIZE)
162 74 : return FALSE;
163 :
164 9314 : nPosInBuffer = 0;
165 : int nToRead;
166 9314 : if (!bLimited)
167 4827 : nToRead = BUFFER_SIZE;
168 4487 : else if (nCurrentPos + BUFFER_SIZE > nStart + nLength)
169 606 : nToRead = nStart + nLength - nCurrentPos;
170 : else
171 3881 : nToRead = BUFFER_SIZE;
172 9314 : nBufferLength = VSIFReadL(abyBuffer, 1, nToRead, f);
173 9314 : if (nBufferLength == 0)
174 0 : return FALSE;
175 :
176 9314 : 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 4948510 : 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 4948510 : if (nPosInBuffer == nBufferLength)
197 : {
198 9388 : if (!FillBuffer() || nPosInBuffer >= nBufferLength)
199 74 : return EOF;
200 : }
201 :
202 4948436 : GByte chRead = abyBuffer[nPosInBuffer];
203 4948436 : nPosInBuffer ++;
204 : #endif
205 4948436 : nCurrentPos ++;
206 4948436 : 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 4583 : void VSIPDFFileStream::reset()
246 : {
247 4583 : nSavedPos = (int)VSIFTellL(f);
248 4583 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
249 4583 : nPosInBuffer = nBufferLength = -1;
250 4583 : }
251 :
252 : /************************************************************************/
253 : /* unfilteredReset() */
254 : /************************************************************************/
255 :
256 0 : void VSIPDFFileStream::unfilteredReset ()
257 : {
258 0 : reset();
259 0 : }
260 :
261 : /************************************************************************/
262 : /* close() */
263 : /************************************************************************/
264 :
265 8574 : void VSIPDFFileStream::close()
266 : {
267 8574 : if (nSavedPos != -1)
268 4380 : VSIFSeekL(f, nCurrentPos = nSavedPos, SEEK_SET);
269 8574 : nSavedPos = -1;
270 8574 : }
271 :
272 : /************************************************************************/
273 : /* setPos() */
274 : /************************************************************************/
275 :
276 937 : void VSIPDFFileStream::setPos(Guint pos, int dir)
277 : {
278 937 : if (dir >= 0)
279 : {
280 645 : VSIFSeekL(f, nCurrentPos = pos, SEEK_SET);
281 : }
282 : else
283 : {
284 292 : if (bLimited == gFalse)
285 : {
286 292 : VSIFSeekL(f, 0, SEEK_END);
287 : }
288 : else
289 : {
290 0 : VSIFSeekL(f, nStart + nLength, SEEK_SET);
291 : }
292 292 : Guint size = (Guint)VSIFTellL(f);
293 292 : if (pos > size)
294 0 : pos = (Guint)size;
295 292 : VSIFSeekL(f, nCurrentPos = size - pos, SEEK_SET);
296 : }
297 937 : nPosInBuffer = nBufferLength = -1;
298 937 : }
299 :
300 : /************************************************************************/
301 : /* moveStart() */
302 : /************************************************************************/
303 :
304 146 : void VSIPDFFileStream::moveStart(int delta)
305 : {
306 146 : nStart += delta;
307 146 : VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
308 146 : nPosInBuffer = nBufferLength = -1;
309 146 : }
310 :
311 : #endif
|