LTP GCOV extension - code coverage report
Current view: directory - port - cpl_vsil_stdin.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 106
Code covered: 14.2 % Executed lines: 15

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_vsil_stdin.cpp 20025 2010-07-11 17:13:02Z 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 20025 2010-07-11 17:13:02Z 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               0 : static void VSIStdinInit()
      58                 : {
      59               0 :     if (pabyBuffer == NULL)
      60                 :     {
      61               0 :         CPLMutexHolder oHolder(&hStdinMutex);
      62               0 :         if (pabyBuffer == NULL)
      63                 :         {
      64                 : #ifdef WIN32
      65                 :             setmode( fileno( stdin ), O_BINARY );
      66                 : #endif
      67               0 :             pabyBuffer = (GByte*)CPLMalloc(BUFFER_SIZE);
      68               0 :             nRealPos = nBufferLen = fread(pabyBuffer, 1, BUFFER_SIZE, stdin);
      69               0 :         }
      70                 :     }
      71               0 : }
      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 );
      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               0 : VSIStdinHandle::VSIStdinHandle()
     119                 : {
     120               0 :     nCurOff = 0;
     121               0 : }
     122                 : 
     123                 : /************************************************************************/
     124                 : /*                          ~VSIStdinHandle()                           */
     125                 : /************************************************************************/
     126                 : 
     127               0 : VSIStdinHandle::~VSIStdinHandle()
     128                 : {
     129               0 : }
     130                 : 
     131                 : /************************************************************************/
     132                 : /*                                Seek()                                */
     133                 : /************************************************************************/
     134                 : 
     135               0 : int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
     136                 : 
     137                 : {
     138               0 :     VSIStdinInit();
     139                 : 
     140               0 :     if (nWhence == SEEK_END)
     141                 :     {
     142               0 :         if (nOffset != 0)
     143                 :         {
     144                 :             CPLError(CE_Failure, CPLE_NotSupported,
     145               0 :                      "Seek(xx != 0, SEEK_END) unsupported on /vsistdin");
     146               0 :             return -1;
     147                 :         }
     148                 : 
     149               0 :         if (nBufferLen < BUFFER_SIZE)
     150                 :         {
     151               0 :             nCurOff = nBufferLen;
     152               0 :             return 0;
     153                 :         }
     154                 : 
     155                 :         CPLError(CE_Failure, CPLE_NotSupported,
     156               0 :                  "Seek(SEEK_END) unsupported on /vsistdin when stdin > 1 MB");
     157               0 :         return -1;
     158                 :     }
     159                 : 
     160               0 :     if (nWhence == SEEK_CUR)
     161               0 :         nOffset += nCurOff;
     162                 : 
     163               0 :     if (nRealPos > nBufferLen && nOffset < nRealPos)
     164                 :     {
     165                 :         CPLError(CE_Failure, CPLE_NotSupported,
     166               0 :                 "backward Seek() unsupported on /vsistdin above first MB");
     167               0 :         return -1;
     168                 :     }
     169                 : 
     170               0 :     if (nOffset < nBufferLen)
     171                 :     {
     172               0 :         nCurOff = nOffset;
     173               0 :         return 0;
     174                 :     }
     175                 : 
     176               0 :     if (nOffset == nCurOff)
     177               0 :         return 0;
     178                 : 
     179                 :     CPLDebug("VSI", "Forward seek from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB,
     180               0 :              nCurOff, nOffset);
     181                 : 
     182                 :     char abyTemp[8192];
     183               0 :     nCurOff = nRealPos;
     184               0 :     while(TRUE)
     185                 :     {
     186               0 :         int nToRead = MIN(8192, nOffset - nCurOff);
     187               0 :         int nRead = fread(abyTemp, 1, nToRead, stdin);
     188               0 :         if (nRead < nToRead)
     189               0 :             return -1;
     190               0 :         nCurOff += nRead;
     191               0 :         nRealPos = nCurOff;
     192               0 :         if (nToRead < 8192)
     193               0 :             break;
     194                 :     }
     195                 : 
     196               0 :     return 0;
     197                 : }
     198                 : 
     199                 : /************************************************************************/
     200                 : /*                                Tell()                                */
     201                 : /************************************************************************/
     202                 : 
     203               0 : vsi_l_offset VSIStdinHandle::Tell()
     204                 : {
     205               0 :     return nCurOff;
     206                 : }
     207                 : 
     208                 : /************************************************************************/
     209                 : /*                                Read()                                */
     210                 : /************************************************************************/
     211                 : 
     212               0 : size_t VSIStdinHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     213                 : 
     214                 : {
     215               0 :     VSIStdinInit();
     216                 : 
     217               0 :     if (nCurOff < nBufferLen)
     218                 :     {
     219               0 :         if (nCurOff + nSize * nCount < nBufferLen)
     220                 :         {
     221               0 :             memcpy(pBuffer, pabyBuffer + nCurOff, nSize * nCount);
     222               0 :             nCurOff += nSize * nCount;
     223               0 :             return nCount;
     224                 :         }
     225                 : 
     226               0 :         memcpy(pBuffer, pabyBuffer + nCurOff, nBufferLen - nCurOff);
     227                 : 
     228                 :         int nRead = fread((GByte*)pBuffer + nBufferLen - nCurOff, 1,
     229               0 :                            nSize * nCount - (nBufferLen - nCurOff), stdin);
     230                 : 
     231               0 :         int nRet = (nRead + nBufferLen - nCurOff) / nSize;
     232                 : 
     233               0 :         nRealPos = nCurOff = nBufferLen + nRead;
     234                 : 
     235               0 :         return nRet;
     236                 :     }
     237                 : 
     238               0 :     int nRet = fread(pBuffer, nSize, nCount, stdin);
     239               0 :     if (nRet < 0)
     240               0 :         return nRet;
     241                 : 
     242               0 :     nCurOff += nRet * nSize;
     243               0 :     nRealPos = nCurOff;
     244                 : 
     245               0 :     return nRet;
     246                 : }
     247                 : 
     248                 : /************************************************************************/
     249                 : /*                               Write()                                */
     250                 : /************************************************************************/
     251                 : 
     252                 : size_t VSIStdinHandle::Write( const void * pBuffer, size_t nSize, 
     253               0 :                                   size_t nCount )
     254                 : 
     255                 : {
     256                 :     CPLError(CE_Failure, CPLE_NotSupported,
     257               0 :              "Write() unsupported on /vsistdin");
     258               0 :     return 0;
     259                 : }
     260                 : 
     261                 : /************************************************************************/
     262                 : /*                                Eof()                                 */
     263                 : /************************************************************************/
     264                 : 
     265               0 : int VSIStdinHandle::Eof()
     266                 : 
     267                 : {
     268               0 :     if (nCurOff < nBufferLen)
     269               0 :         return FALSE;
     270               0 :     return feof(stdin);
     271                 : }
     272                 : 
     273                 : /************************************************************************/
     274                 : /*                               Close()                                */
     275                 : /************************************************************************/
     276                 : 
     277               0 : int VSIStdinHandle::Close()
     278                 : 
     279                 : {
     280               0 :     return 0;
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /* ==================================================================== */
     285                 : /*                       VSIStdinFilesystemHandler                     */
     286                 : /* ==================================================================== */
     287                 : /************************************************************************/
     288                 : 
     289                 : /************************************************************************/
     290                 : /*                        VSIStdinFilesystemHandler()                   */
     291                 : /************************************************************************/
     292                 : 
     293             447 : VSIStdinFilesystemHandler::VSIStdinFilesystemHandler()
     294                 : {
     295             447 :     hStdinMutex = NULL;
     296             447 :     pabyBuffer = NULL;
     297             447 :     nBufferLen = 0;
     298             447 :     nRealPos = 0;
     299             447 : }
     300                 : 
     301                 : /************************************************************************/
     302                 : /*                       ~VSIStdinFilesystemHandler()                   */
     303                 : /************************************************************************/
     304                 : 
     305             432 : VSIStdinFilesystemHandler::~VSIStdinFilesystemHandler()
     306                 : {
     307             432 :     if( hStdinMutex != NULL )
     308               0 :         CPLDestroyMutex( hStdinMutex );
     309             432 :     hStdinMutex = NULL;
     310                 : 
     311             432 :     CPLFree(pabyBuffer);
     312             432 :     pabyBuffer = NULL;
     313             432 : }
     314                 : 
     315                 : /************************************************************************/
     316                 : /*                                Open()                                */
     317                 : /************************************************************************/
     318                 : 
     319                 : VSIVirtualHandle *
     320                 : VSIStdinFilesystemHandler::Open( const char *pszFilename, 
     321               0 :                                  const char *pszAccess )
     322                 : 
     323                 : {
     324               0 :     if (strcmp(pszFilename, "/vsistdin/") != 0)
     325               0 :         return NULL;
     326                 : 
     327               0 :     if ( strchr(pszAccess, 'w') != NULL ||
     328                 :          strchr(pszAccess, '+') != NULL )
     329                 :     {
     330                 :         CPLError(CE_Failure, CPLE_NotSupported,
     331               0 :                  "Write or update mode not supported on /vsistdin");
     332               0 :         return NULL;
     333                 :     }
     334                 : 
     335               0 :     return new VSIStdinHandle;
     336                 : }
     337                 : 
     338                 : /************************************************************************/
     339                 : /*                                Stat()                                */
     340                 : /************************************************************************/
     341                 : 
     342                 : int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
     343               0 :                                       VSIStatBufL * pStatBuf )
     344                 : 
     345                 : {
     346               0 :     memset( pStatBuf, 0, sizeof(VSIStatBufL) );
     347                 : 
     348               0 :     if (strcmp(pszFilename, "/vsistdin/") != 0)
     349               0 :         return -1;
     350                 : 
     351               0 :     VSIStdinInit();
     352                 : 
     353               0 :     pStatBuf->st_size = nBufferLen;
     354               0 :     pStatBuf->st_mode = S_IFREG;
     355               0 :     return 0;
     356                 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /*                       VSIInstallStdinHandler()                      */
     360                 : /************************************************************************/
     361                 : 
     362             447 : void VSIInstallStdinHandler()
     363                 : 
     364                 : {
     365             447 :     VSIFileManager::InstallHandler( "/vsistdin/", new VSIStdinFilesystemHandler );
     366             447 : }

Generated by: LTP GCOV extension version 1.5