Introduced FileHandler classes
Wrapper classes to handle resources following the RAII principle
This commit is contained in:
parent
2f8ec16043
commit
909ce98c5b
2 changed files with 110 additions and 59 deletions
|
@ -24,6 +24,60 @@
|
|||
#define CHUNK 16384
|
||||
|
||||
|
||||
//! RAII class to handle s file resource
|
||||
class FileHandler
|
||||
{
|
||||
FILE* file;
|
||||
|
||||
public:
|
||||
explicit FileHandler( const char* path, const char* mode )
|
||||
: file{ nullptr }
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
fopen_s( &this->file, path, mode );
|
||||
#else
|
||||
this->file = fopen( path, mode );
|
||||
#endif
|
||||
}
|
||||
|
||||
~FileHandler()
|
||||
{
|
||||
if ( this->valid() ) {
|
||||
fclose( this->file );
|
||||
}
|
||||
}
|
||||
|
||||
FileHandler(const FileHandler&) = delete;
|
||||
FileHandler(FileHandler&&) = delete;
|
||||
FileHandler& operator=(const FileHandler&) = delete;
|
||||
FileHandler& operator=(FileHandler&&) = delete;
|
||||
|
||||
inline operator FILE*()
|
||||
{
|
||||
return this->file;
|
||||
}
|
||||
|
||||
inline bool valid() const noexcept
|
||||
{
|
||||
return this->file != NULL;
|
||||
}
|
||||
|
||||
inline bool error() const noexcept
|
||||
{
|
||||
return ferror( this->file );
|
||||
}
|
||||
|
||||
inline void close()
|
||||
{
|
||||
if ( fclose( this->file ) ) {
|
||||
throw GenericException( "Failed to close file pointer" );
|
||||
}
|
||||
this->file = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace GZutils
|
||||
{
|
||||
|
||||
|
@ -49,24 +103,16 @@ void readFile( const std::string& path, std::string& content )
|
|||
}
|
||||
|
||||
if ( successful ) {
|
||||
#ifdef _MSC_VER
|
||||
FILE* file;
|
||||
const int err{ fopen_s( &file, path.c_str(), "rb" ) };
|
||||
/*FILE *dest = fopen ( out_path.c_str(), "wb" );*/
|
||||
if ( file == NULL || err != 0 ) {
|
||||
#else
|
||||
FILE* file = fopen( path.c_str(), "rb" );
|
||||
/*FILE *dest = fopen( out_path.c_str(), "wb" );*/
|
||||
if ( file == NULL ) {
|
||||
#endif
|
||||
FileHandler file{ path.c_str(), "rb" };
|
||||
if ( ! file.valid() ) {
|
||||
// unable to open the file
|
||||
//throw("cannot read");
|
||||
return;
|
||||
}
|
||||
/*FILE *dest = fopen( out_path.c_str(), "wb" );*/
|
||||
// decompress until deflate stream ends or end of file is reached
|
||||
do {
|
||||
strm.avail_in = static_cast<unsigned>(fread( in, 1, CHUNK, file ));
|
||||
if ( ferror( file ) ) {
|
||||
if ( file.error() ) {
|
||||
// error reading
|
||||
(void)inflateEnd( &strm );
|
||||
/*successful = false;*/
|
||||
|
@ -111,11 +157,7 @@ void readFile( const std::string& path, std::string& content )
|
|||
// clean up and return
|
||||
(void)inflateEnd( &strm );
|
||||
successful = (ret == Z_STREAM_END) ? true : false;
|
||||
if ( fclose( file ) ) {
|
||||
// error while trying to close file pointer
|
||||
throw GenericException( "Failed to close file pointer" );
|
||||
}
|
||||
//delete file;
|
||||
file.close(); // throws GenericException on failure
|
||||
}
|
||||
if ( content.empty() ) {
|
||||
// probably not a gzip compressed file
|
||||
|
|
|
@ -10,6 +10,49 @@
|
|||
#include <fstream>
|
||||
|
||||
|
||||
//! RAII class to handle a file stream resource
|
||||
template<typename Stream>
|
||||
class FileHandler
|
||||
{
|
||||
Stream file;
|
||||
|
||||
public:
|
||||
explicit FileHandler( const std::string& path )
|
||||
: file{ path }
|
||||
{
|
||||
if ( ! this->file.is_open() ) {
|
||||
throw std::ios_base::failure( "file is not open" );
|
||||
}
|
||||
if ( ! this->file.good() ) {
|
||||
throw std::ios_base::failure( "file is not good" );
|
||||
}
|
||||
}
|
||||
|
||||
~FileHandler()
|
||||
{
|
||||
if ( this->file.is_open() ) {
|
||||
this->file.close();
|
||||
}
|
||||
}
|
||||
|
||||
FileHandler(const FileHandler&) = delete;
|
||||
FileHandler(FileHandler&&) = delete;
|
||||
FileHandler& operator=(const FileHandler&) = delete;
|
||||
FileHandler& operator=(FileHandler&&) = delete;
|
||||
|
||||
inline Stream& operator*()
|
||||
{
|
||||
return this->file;
|
||||
}
|
||||
|
||||
inline void setException( const std::ios_base::iostate e )
|
||||
{
|
||||
this->file.exceptions( e );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace IOutils
|
||||
{
|
||||
|
||||
|
@ -96,39 +139,22 @@ bool renameAsCopy( std::string_view path, std::error_code& err ) noexcept(true)
|
|||
void readFile( const std::string& path, std::string& content )
|
||||
{
|
||||
// read the whole file
|
||||
std::ifstream file;
|
||||
try {
|
||||
/*constexpr std::size_t read_size = std::size_t(4096);*/
|
||||
file = std::ifstream(path);
|
||||
if ( ! file.is_open() ) {
|
||||
throw std::ios_base::failure( "file is not open" );
|
||||
}
|
||||
if ( ! file.good() ) {
|
||||
throw std::ios_base::failure( "file is not good" );
|
||||
}
|
||||
FileHandler<std::ifstream> file{ path }; // throws std::ios_base::failure on failure
|
||||
// add bit exceptions
|
||||
file.exceptions( std::ifstream::failbit );
|
||||
file.exceptions( std::ios_base::badbit );
|
||||
file.setException( std::ifstream::failbit );
|
||||
file.setException( std::ios_base::badbit );
|
||||
// read the whole file
|
||||
content = std::string(
|
||||
std::istreambuf_iterator<char>( file ),
|
||||
std::istreambuf_iterator<char>( *file ),
|
||||
std::istreambuf_iterator<char>() );
|
||||
|
||||
} catch ( const std::ios_base::failure& ) {
|
||||
// failed reading
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
throw;
|
||||
} catch (...) {
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
throw std::exception(); // already catched
|
||||
}
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,37 +244,20 @@ void randomLines( const std::string& path, std::vector<std::string>& lines, cons
|
|||
|
||||
void writeOnFile( const std::string& path, std::string_view content )
|
||||
{
|
||||
std::ofstream file;
|
||||
try {
|
||||
file.open( path );
|
||||
if ( ! file.is_open() ) {
|
||||
throw std::ios_base::failure( "file is not open" );
|
||||
}
|
||||
if ( ! file.good() ) {
|
||||
throw std::ios_base::failure( "file is not good" );
|
||||
}
|
||||
FileHandler<std::ofstream> file{ path }; // throws std::ios_base::failure on failure
|
||||
// add bit exceptions
|
||||
file.exceptions( std::ifstream::failbit );
|
||||
file.exceptions( std::ios_base::badbit );
|
||||
file.setException( std::ios_base::failbit );
|
||||
file.setException( std::ios_base::badbit );
|
||||
// write the content
|
||||
file << content << std::endl;
|
||||
*file << content << std::endl;
|
||||
|
||||
} catch ( const std::ios_base::failure& ) {
|
||||
// failed writing
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
throw;
|
||||
} catch (...) {
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
throw std::exception(); // already catched
|
||||
}
|
||||
|
||||
if ( file.is_open() ) {
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace IOUtils
|
||||
|
|
Loading…
Reference in a new issue