/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined( INCLUDED_STREAM_FILESTREAM_H ) #define INCLUDED_STREAM_FILESTREAM_H #include "idatastream.h" #include #include namespace FileStreamDetail { inline int whence_for_seekdir( SeekableStream::seekdir direction ){ switch ( direction ) { case SeekableStream::cur: return SEEK_CUR; case SeekableStream::end: return SEEK_END; default: break; } return SEEK_SET; } } /// \brief A wrapper around a file input stream opened for reading in binary mode. Similar to std::ifstream. /// /// - Maintains a valid file handle associated with a name passed to the constructor. /// - Implements SeekableInputStream. class FileInputStream : public SeekableInputStream { std::FILE* m_file; public: FileInputStream( const char* name ){ m_file = name[0] == '\0' ? 0 : fopen( name, "rb" ); } ~FileInputStream(){ if ( !failed() ) { fclose( m_file ); } } bool failed() const { return m_file == 0; } size_type read( byte_type* buffer, size_type length ){ return fread( buffer, 1, length, m_file ); } size_type seek( size_type position ){ return fseek( m_file, static_cast( position ), SEEK_SET ); } size_type seek( offset_type offset, seekdir direction ){ return fseek( m_file, offset, FileStreamDetail::whence_for_seekdir( direction ) ); } size_type tell() const { return ftell( m_file ); } std::FILE* file(){ return m_file; } }; /// \brief A wrapper around a FileInputStream limiting access. /// /// - Maintains an input stream. /// - Provides input starting at an offset in the file for a limited range. class SubFileInputStream : public InputStream { FileInputStream& m_istream; size_type m_remaining; public: typedef FileInputStream::position_type position_type; SubFileInputStream( FileInputStream& istream, position_type offset, size_type size ) : m_istream( istream ), m_remaining( size ){ m_istream.seek( offset ); } size_type read( byte_type* buffer, size_type length ){ size_type result = m_istream.read( buffer, std::min( length, m_remaining ) ); m_remaining -= result; return result; } }; /// \brief A wrapper around a stdc file stream opened for writing in binary mode. Similar to std::ofstream.. /// /// - Maintains a valid file handle associated with a name passed to the constructor. /// - Implements SeekableInputStream. class FileOutputStream : public SeekableOutputStream { std::FILE* m_file; public: FileOutputStream( const char* name ){ m_file = name[0] == '\0' ? 0 : fopen( name, "wb" ); } ~FileOutputStream(){ if ( !failed() ) { fclose( m_file ); } } bool failed() const { return m_file == 0; } size_type write( const byte_type* buffer, size_type length ){ return fwrite( buffer, 1, length, m_file ); } size_type seek( size_type position ){ return fseek( m_file, static_cast( position ), SEEK_SET ); } size_type seek( offset_type offset, seekdir direction ){ return fseek( m_file, offset, FileStreamDetail::whence_for_seekdir( direction ) ); } size_type tell() const { return ftell( m_file ); } }; inline bool file_copy( const char* source, const char* target ){ const std::size_t buffer_size = 1024; unsigned char buffer[buffer_size]; FileInputStream sourceFile( source ); if ( sourceFile.failed() ) { return false; } FileOutputStream targetFile( target ); if ( targetFile.failed() ) { return false; } for (;; ) { std::size_t size = sourceFile.read( buffer, buffer_size ); if ( size == 0 ) { break; } if ( targetFile.write( buffer, size ) != size ) { return false; } } return true; } #endif