LCOV - code coverage report
Current view: directory - port - cpl_vsil_stdin.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 108 86 79.6 %
Date: 2012-12-26 Functions: 21 13 61.9 %

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

Generated by: LCOV version 1.7