EVOLUTION-MANAGER
Edit File: cpl_vsil_stdout.cpp
/********************************************************************** * * Project: CPL - Common Portability Library * Purpose: Implement VSI large file api for stdout * Author: Even Rouault, <even dot rouault at mines dash paris dot org> * ********************************************************************** * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "cpl_port.h" #include "cpl_vsi.h" #include <cstddef> #include <cstdio> #include <cstring> #if HAVE_FCNTL_H # include <fcntl.h> #endif #include "cpl_error.h" #include "cpl_vsi_virtual.h" #ifdef WIN32 #include <io.h> #include <fcntl.h> #endif CPL_CVSID("$Id: cpl_vsil_stdout.cpp 5524ee5324f7bd364d391d842a6488c90c0186a7 2018-04-02 16:20:13 +0200 Even Rouault $") static VSIWriteFunction pWriteFunction = fwrite; static FILE* pWriteStream = stdout; /************************************************************************/ /* VSIStdoutSetRedirection() */ /************************************************************************/ /** Set an alternative write function and output file handle instead of * fwrite() / stdout. * * @param pFct Function with same signature as fwrite() * @param stream File handle on which to output. Passed to pFct. * * @since GDAL 2.0 */ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream ) { pWriteFunction = pFct; pWriteStream = stream; } //! @cond Doxygen_Suppress /************************************************************************/ /* ==================================================================== */ /* VSIStdoutFilesystemHandler */ /* ==================================================================== */ /************************************************************************/ class VSIStdoutFilesystemHandler final : public VSIFilesystemHandler { public: VSIVirtualHandle *Open( const char *pszFilename, const char *pszAccess, bool bSetError ) override; int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ) override; }; /************************************************************************/ /* ==================================================================== */ /* VSIStdoutHandle */ /* ==================================================================== */ /************************************************************************/ class VSIStdoutHandle final : public VSIVirtualHandle { vsi_l_offset m_nOffset; public: VSIStdoutHandle() : m_nOffset(0) {} ~VSIStdoutHandle() override {} int Seek( vsi_l_offset nOffset, int nWhence ) override; vsi_l_offset Tell() override; size_t Read( void *pBuffer, size_t nSize, size_t nMemb ) override; size_t Write( const void *pBuffer, size_t nSize, size_t nMemb ) override; int Eof() override; int Flush() override; int Close() override; }; /************************************************************************/ /* Seek() */ /************************************************************************/ int VSIStdoutHandle::Seek( vsi_l_offset nOffset, int nWhence ) { if( nOffset == 0 && (nWhence == SEEK_END || nWhence == SEEK_CUR) ) return 0; if( nWhence == SEEK_SET && nOffset == Tell() ) return 0; CPLError(CE_Failure, CPLE_NotSupported, "Seek() unsupported on /vsistdout"); return -1; } /************************************************************************/ /* Tell() */ /************************************************************************/ vsi_l_offset VSIStdoutHandle::Tell() { return m_nOffset; } /************************************************************************/ /* Flush() */ /************************************************************************/ int VSIStdoutHandle::Flush() { if( pWriteStream == stdout ) return fflush( stdout ); else return 0; } /************************************************************************/ /* Read() */ /************************************************************************/ size_t VSIStdoutHandle::Read( void * /* pBuffer */, size_t /* nSize */, size_t /* nCount */ ) { CPLError(CE_Failure, CPLE_NotSupported, "Read() unsupported on /vsistdout"); return 0; } /************************************************************************/ /* Write() */ /************************************************************************/ size_t VSIStdoutHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { size_t nRet = pWriteFunction(pBuffer, nSize, nCount, pWriteStream); m_nOffset += nSize * nRet; return nRet; } /************************************************************************/ /* Eof() */ /************************************************************************/ int VSIStdoutHandle::Eof() { return 0; } /************************************************************************/ /* Close() */ /************************************************************************/ int VSIStdoutHandle::Close() { return Flush(); } /************************************************************************/ /* ==================================================================== */ /* VSIStdoutFilesystemHandler */ /* ==================================================================== */ /************************************************************************/ /************************************************************************/ /* Open() */ /************************************************************************/ VSIVirtualHandle * VSIStdoutFilesystemHandler::Open( const char * /* pszFilename */, const char *pszAccess, bool /* bSetError */ ) { if ( strchr(pszAccess, 'r') != nullptr || strchr(pszAccess, '+') != nullptr ) { CPLError(CE_Failure, CPLE_NotSupported, "Read or update mode not supported on /vsistdout"); return nullptr; } #ifdef WIN32 if ( strchr(pszAccess, 'b') != nullptr ) setmode( fileno( stdout ), O_BINARY ); #endif return new VSIStdoutHandle; } /************************************************************************/ /* Stat() */ /************************************************************************/ int VSIStdoutFilesystemHandler::Stat( const char * /* pszFilename */, VSIStatBufL * pStatBuf, int /* nFlags */ ) { memset( pStatBuf, 0, sizeof(VSIStatBufL) ); return -1; } /************************************************************************/ /* ==================================================================== */ /* VSIStdoutRedirectFilesystemHandler */ /* ==================================================================== */ /************************************************************************/ class VSIStdoutRedirectFilesystemHandler final : public VSIFilesystemHandler { public: VSIVirtualHandle *Open( const char *pszFilename, const char *pszAccess, bool bSetError ) override; int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ) override; }; /************************************************************************/ /* ==================================================================== */ /* VSIStdoutRedirectHandle */ /* ==================================================================== */ /************************************************************************/ class VSIStdoutRedirectHandle final : public VSIVirtualHandle { VSIVirtualHandle* m_poHandle; public: explicit VSIStdoutRedirectHandle( VSIVirtualHandle* poHandle ); ~VSIStdoutRedirectHandle() override; int Seek( vsi_l_offset nOffset, int nWhence ) override; vsi_l_offset Tell() override; size_t Read( void *pBuffer, size_t nSize, size_t nMemb ) override; size_t Write( const void *pBuffer, size_t nSize, size_t nMemb ) override; int Eof() override; int Flush() override; int Close() override; }; /************************************************************************/ /* VSIStdoutRedirectHandle() */ /************************************************************************/ VSIStdoutRedirectHandle::VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle) { m_poHandle = poHandle; } /************************************************************************/ /* ~VSIStdoutRedirectHandle() */ /************************************************************************/ VSIStdoutRedirectHandle::~VSIStdoutRedirectHandle() { delete m_poHandle; } /************************************************************************/ /* Seek() */ /************************************************************************/ int VSIStdoutRedirectHandle::Seek( vsi_l_offset /* nOffset */, int /* nWhence */ ) { CPLError(CE_Failure, CPLE_NotSupported, "Seek() unsupported on /vsistdout_redirect"); return -1; } /************************************************************************/ /* Tell() */ /************************************************************************/ vsi_l_offset VSIStdoutRedirectHandle::Tell() { return m_poHandle->Tell(); } /************************************************************************/ /* Flush() */ /************************************************************************/ int VSIStdoutRedirectHandle::Flush() { return m_poHandle->Flush(); } /************************************************************************/ /* Read() */ /************************************************************************/ size_t VSIStdoutRedirectHandle::Read( void * /* pBuffer */, size_t /* nSize */, size_t /* nCount */ ) { CPLError(CE_Failure, CPLE_NotSupported, "Read() unsupported on /vsistdout_redirect"); return 0; } /************************************************************************/ /* Write() */ /************************************************************************/ size_t VSIStdoutRedirectHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { return m_poHandle->Write(pBuffer, nSize, nCount); } /************************************************************************/ /* Eof() */ /************************************************************************/ int VSIStdoutRedirectHandle::Eof() { return m_poHandle->Eof(); } /************************************************************************/ /* Close() */ /************************************************************************/ int VSIStdoutRedirectHandle::Close() { return m_poHandle->Close(); } /************************************************************************/ /* ==================================================================== */ /* VSIStdoutRedirectFilesystemHandler */ /* ==================================================================== */ /************************************************************************/ /************************************************************************/ /* Open() */ /************************************************************************/ VSIVirtualHandle * VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename, const char *pszAccess, bool /* bSetError */ ) { if ( strchr(pszAccess, 'r') != nullptr || strchr(pszAccess, '+') != nullptr ) { CPLError(CE_Failure, CPLE_NotSupported, "Read or update mode not supported on /vsistdout_redirect"); return nullptr; } VSIVirtualHandle* poHandle = reinterpret_cast<VSIVirtualHandle*>( VSIFOpenL(pszFilename + strlen("/vsistdout_redirect/"), pszAccess)); if (poHandle == nullptr) return nullptr; return new VSIStdoutRedirectHandle(poHandle); } /************************************************************************/ /* Stat() */ /************************************************************************/ int VSIStdoutRedirectFilesystemHandler::Stat( const char * /* pszFilename */, VSIStatBufL * pStatBuf, int /* nFlags */ ) { memset( pStatBuf, 0, sizeof(VSIStatBufL) ); return -1; } //! @endcond /************************************************************************/ /* VSIInstallStdoutHandler() */ /************************************************************************/ /** * \brief Install /vsistdout/ file system handler * * A special file handler is installed that allows writing to the standard * output stream. * * The file operations available are of course limited to Write(). * * A variation of this file system exists as the /vsistdout_redirect/ file * system handler, where the output function can be defined with * VSIStdoutSetRedirection(). * * @since GDAL 1.8.0 */ void VSIInstallStdoutHandler() { VSIFileManager::InstallHandler( "/vsistdout/", new VSIStdoutFilesystemHandler ); VSIFileManager::InstallHandler( "/vsistdout_redirect/", new VSIStdoutRedirectFilesystemHandler ); }