~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to port/cpl_vsil_stdin.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
 * $Id: cpl_vsil_stdin.cpp 21689 2011-02-12 12:18:14Z rouault $
 
3
 *
 
4
 * Project:  CPL - Common Portability Library
 
5
 * Purpose:  Implement VSI large file api for stdin
 
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 OR
 
22
 * 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
#include "cpl_port.h"
 
31
#include "cpl_error.h"
 
32
#include "cpl_vsi_virtual.h"
 
33
#include "cpl_multiproc.h"
 
34
 
 
35
#include <stdio.h>
 
36
#ifdef WIN32
 
37
#include <io.h>
 
38
#include <fcntl.h>
 
39
#endif
 
40
 
 
41
CPL_CVSID("$Id: cpl_vsil_stdin.cpp 21689 2011-02-12 12:18:14Z rouault $");
 
42
 
 
43
/* We buffer the first 1MB of standard input to enable drivers */
 
44
/* to autodetect data. In the first MB, backward and forward seeking */
 
45
/* is allowed, after only forward seeking will work */
 
46
#define BUFFER_SIZE (1024 * 1024)
 
47
 
 
48
static void* hStdinMutex;
 
49
static GByte* pabyBuffer;
 
50
static GUInt32 nBufferLen;
 
51
static GUIntBig nRealPos;
 
52
 
 
53
/************************************************************************/
 
54
/*                           VSIStdinInit()                             */
 
55
/************************************************************************/
 
56
 
 
57
static void VSIStdinInit()
 
58
{
 
59
    if (pabyBuffer == NULL)
 
60
    {
 
61
        CPLMutexHolder oHolder(&hStdinMutex);
 
62
        if (pabyBuffer == NULL)
 
63
        {
 
64
#ifdef WIN32
 
65
            setmode( fileno( stdin ), O_BINARY );
 
66
#endif
 
67
            pabyBuffer = (GByte*)CPLMalloc(BUFFER_SIZE);
 
68
            nRealPos = nBufferLen = fread(pabyBuffer, 1, BUFFER_SIZE, stdin);
 
69
        }
 
70
    }
 
71
}
 
72
 
 
73
/************************************************************************/
 
74
/* ==================================================================== */
 
75
/*                       VSIStdinFilesystemHandler                     */
 
76
/* ==================================================================== */
 
77
/************************************************************************/
 
78
 
 
79
class VSIStdinFilesystemHandler : public VSIFilesystemHandler
 
80
{
 
81
public:
 
82
                              VSIStdinFilesystemHandler();
 
83
    virtual                  ~VSIStdinFilesystemHandler();
 
84
 
 
85
    virtual VSIVirtualHandle *Open( const char *pszFilename, 
 
86
                                    const char *pszAccess);
 
87
    virtual int               Stat( const char *pszFilename,
 
88
                                    VSIStatBufL *pStatBuf, int nFlags );
 
89
};
 
90
 
 
91
/************************************************************************/
 
92
/* ==================================================================== */
 
93
/*                        VSIStdinHandle                               */
 
94
/* ==================================================================== */
 
95
/************************************************************************/
 
96
 
 
97
class VSIStdinHandle : public VSIVirtualHandle
 
98
{
 
99
  private:
 
100
    GUIntBig nCurOff;
 
101
 
 
102
  public:
 
103
                      VSIStdinHandle();
 
104
    virtual          ~VSIStdinHandle();
 
105
 
 
106
    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
 
107
    virtual vsi_l_offset Tell();
 
108
    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
 
109
    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
 
110
    virtual int       Eof();
 
111
    virtual int       Close();
 
112
};
 
113
 
 
114
/************************************************************************/
 
115
/*                           VSIStdinHandle()                           */
 
116
/************************************************************************/
 
117
 
 
118
VSIStdinHandle::VSIStdinHandle()
 
119
{
 
120
    nCurOff = 0;
 
121
}
 
122
 
 
123
/************************************************************************/
 
124
/*                          ~VSIStdinHandle()                           */
 
125
/************************************************************************/
 
126
 
 
127
VSIStdinHandle::~VSIStdinHandle()
 
128
{
 
129
}
 
130
 
 
131
/************************************************************************/
 
132
/*                                Seek()                                */
 
133
/************************************************************************/
 
134
 
 
135
int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
136
 
 
137
{
 
138
    VSIStdinInit();
 
139
 
 
140
    if (nWhence == SEEK_END)
 
141
    {
 
142
        if (nOffset != 0)
 
143
        {
 
144
            CPLError(CE_Failure, CPLE_NotSupported,
 
145
                     "Seek(xx != 0, SEEK_END) unsupported on /vsistdin");
 
146
            return -1;
 
147
        }
 
148
 
 
149
        if (nBufferLen < BUFFER_SIZE)
 
150
        {
 
151
            nCurOff = nBufferLen;
 
152
            return 0;
 
153
        }
 
154
 
 
155
        CPLError(CE_Failure, CPLE_NotSupported,
 
156
                 "Seek(SEEK_END) unsupported on /vsistdin when stdin > 1 MB");
 
157
        return -1;
 
158
    }
 
159
 
 
160
    if (nWhence == SEEK_CUR)
 
161
        nOffset += nCurOff;
 
162
 
 
163
    if (nRealPos > nBufferLen && nOffset < nRealPos)
 
164
    {
 
165
        CPLError(CE_Failure, CPLE_NotSupported,
 
166
                "backward Seek() unsupported on /vsistdin above first MB");
 
167
        return -1;
 
168
    }
 
169
 
 
170
    if (nOffset < nBufferLen)
 
171
    {
 
172
        nCurOff = nOffset;
 
173
        return 0;
 
174
    }
 
175
 
 
176
    if (nOffset == nCurOff)
 
177
        return 0;
 
178
 
 
179
    CPLDebug("VSI", "Forward seek from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB,
 
180
             nCurOff, nOffset);
 
181
 
 
182
    char abyTemp[8192];
 
183
    nCurOff = nRealPos;
 
184
    while(TRUE)
 
185
    {
 
186
        int nToRead = (int) MIN(8192, nOffset - nCurOff);
 
187
        int nRead = fread(abyTemp, 1, nToRead, stdin);
 
188
        if (nRead < nToRead)
 
189
            return -1;
 
190
        nCurOff += nRead;
 
191
        nRealPos = nCurOff;
 
192
        if (nToRead < 8192)
 
193
            break;
 
194
    }
 
195
 
 
196
    return 0;
 
197
}
 
198
 
 
199
/************************************************************************/
 
200
/*                                Tell()                                */
 
201
/************************************************************************/
 
202
 
 
203
vsi_l_offset VSIStdinHandle::Tell()
 
204
{
 
205
    return nCurOff;
 
206
}
 
207
 
 
208
/************************************************************************/
 
209
/*                                Read()                                */
 
210
/************************************************************************/
 
211
 
 
212
size_t VSIStdinHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
213
 
 
214
{
 
215
    VSIStdinInit();
 
216
 
 
217
    if (nCurOff < nBufferLen)
 
218
    {
 
219
        if (nCurOff + nSize * nCount < nBufferLen)
 
220
        {
 
221
            memcpy(pBuffer, pabyBuffer + nCurOff, nSize * nCount);
 
222
            nCurOff += nSize * nCount;
 
223
            return nCount;
 
224
        }
 
225
 
 
226
        memcpy(pBuffer, pabyBuffer + nCurOff, (size_t)(nBufferLen - nCurOff));
 
227
 
 
228
        int nRead = fread((GByte*)pBuffer + nBufferLen - nCurOff, 1,
 
229
                          (size_t)(nSize*nCount - (nBufferLen-nCurOff)), stdin);
 
230
 
 
231
        int nRet = (int) ((nRead + nBufferLen - nCurOff) / nSize);
 
232
 
 
233
        nRealPos = nCurOff = nBufferLen + nRead;
 
234
 
 
235
        return nRet;
 
236
    }
 
237
 
 
238
    int nRet = fread(pBuffer, nSize, nCount, stdin);
 
239
    if (nRet < 0)
 
240
        return nRet;
 
241
 
 
242
    nCurOff += nRet * nSize;
 
243
    nRealPos = nCurOff;
 
244
 
 
245
    return nRet;
 
246
}
 
247
 
 
248
/************************************************************************/
 
249
/*                               Write()                                */
 
250
/************************************************************************/
 
251
 
 
252
size_t VSIStdinHandle::Write( const void * pBuffer, size_t nSize, 
 
253
                                  size_t nCount )
 
254
 
 
255
{
 
256
    CPLError(CE_Failure, CPLE_NotSupported,
 
257
             "Write() unsupported on /vsistdin");
 
258
    return 0;
 
259
}
 
260
 
 
261
/************************************************************************/
 
262
/*                                Eof()                                 */
 
263
/************************************************************************/
 
264
 
 
265
int VSIStdinHandle::Eof()
 
266
 
 
267
{
 
268
    if (nCurOff < nBufferLen)
 
269
        return FALSE;
 
270
    return feof(stdin);
 
271
}
 
272
 
 
273
/************************************************************************/
 
274
/*                               Close()                                */
 
275
/************************************************************************/
 
276
 
 
277
int VSIStdinHandle::Close()
 
278
 
 
279
{
 
280
    return 0;
 
281
}
 
282
 
 
283
/************************************************************************/
 
284
/* ==================================================================== */
 
285
/*                       VSIStdinFilesystemHandler                     */
 
286
/* ==================================================================== */
 
287
/************************************************************************/
 
288
 
 
289
/************************************************************************/
 
290
/*                        VSIStdinFilesystemHandler()                   */
 
291
/************************************************************************/
 
292
 
 
293
VSIStdinFilesystemHandler::VSIStdinFilesystemHandler()
 
294
{
 
295
    hStdinMutex = NULL;
 
296
    pabyBuffer = NULL;
 
297
    nBufferLen = 0;
 
298
    nRealPos = 0;
 
299
}
 
300
 
 
301
/************************************************************************/
 
302
/*                       ~VSIStdinFilesystemHandler()                   */
 
303
/************************************************************************/
 
304
 
 
305
VSIStdinFilesystemHandler::~VSIStdinFilesystemHandler()
 
306
{
 
307
    if( hStdinMutex != NULL )
 
308
        CPLDestroyMutex( hStdinMutex );
 
309
    hStdinMutex = NULL;
 
310
 
 
311
    CPLFree(pabyBuffer);
 
312
    pabyBuffer = NULL;
 
313
}
 
314
 
 
315
/************************************************************************/
 
316
/*                                Open()                                */
 
317
/************************************************************************/
 
318
 
 
319
VSIVirtualHandle *
 
320
VSIStdinFilesystemHandler::Open( const char *pszFilename, 
 
321
                                 const char *pszAccess )
 
322
 
 
323
{
 
324
    if (strcmp(pszFilename, "/vsistdin/") != 0)
 
325
        return NULL;
 
326
 
 
327
    if ( strchr(pszAccess, 'w') != NULL ||
 
328
         strchr(pszAccess, '+') != NULL )
 
329
    {
 
330
        CPLError(CE_Failure, CPLE_NotSupported,
 
331
                 "Write or update mode not supported on /vsistdin");
 
332
        return NULL;
 
333
    }
 
334
 
 
335
    return new VSIStdinHandle;
 
336
}
 
337
 
 
338
/************************************************************************/
 
339
/*                                Stat()                                */
 
340
/************************************************************************/
 
341
 
 
342
int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
 
343
                                     VSIStatBufL * pStatBuf,
 
344
                                     int nFlags )
 
345
 
 
346
{
 
347
    memset( pStatBuf, 0, sizeof(VSIStatBufL) );
 
348
 
 
349
    if (strcmp(pszFilename, "/vsistdin/") != 0)
 
350
        return -1;
 
351
 
 
352
    VSIStdinInit();
 
353
 
 
354
    pStatBuf->st_size = nBufferLen;
 
355
    pStatBuf->st_mode = S_IFREG;
 
356
    return 0;
 
357
}
 
358
 
 
359
/************************************************************************/
 
360
/*                       VSIInstallStdinHandler()                       */
 
361
/************************************************************************/
 
362
 
 
363
/**
 
364
 * \brief Install /vsistdin/ file system handler
 
365
 *
 
366
 * A special file handler is installed that allows reading from the standard
 
367
 * input steam.
 
368
 *
 
369
 * The file operations available are of course limited to Read() and
 
370
 * forward Seek() (full seek in the first MB of a file).
 
371
 *
 
372
 * @since GDAL 1.8.0
 
373
 */
 
374
void VSIInstallStdinHandler()
 
375
 
 
376
{
 
377
    VSIFileManager::InstallHandler( "/vsistdin/", new VSIStdinFilesystemHandler );
 
378
}