Introduced FileHandler classes
Wrapper classes to handle resources following the RAII principle
This commit is contained in:
parent
2f8ec16043
commit
909ce98c5b
|
@ -24,6 +24,60 @@
|
||||||
#define CHUNK 16384
|
#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
|
namespace GZutils
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -49,24 +103,16 @@ void readFile( const std::string& path, std::string& content )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( successful ) {
|
if ( successful ) {
|
||||||
#ifdef _MSC_VER
|
FileHandler file{ path.c_str(), "rb" };
|
||||||
FILE* file;
|
if ( ! file.valid() ) {
|
||||||
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
|
|
||||||
// unable to open the file
|
// unable to open the file
|
||||||
//throw("cannot read");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/*FILE *dest = fopen( out_path.c_str(), "wb" );*/
|
||||||
// decompress until deflate stream ends or end of file is reached
|
// decompress until deflate stream ends or end of file is reached
|
||||||
do {
|
do {
|
||||||
strm.avail_in = static_cast<unsigned>(fread( in, 1, CHUNK, file ));
|
strm.avail_in = static_cast<unsigned>(fread( in, 1, CHUNK, file ));
|
||||||
if ( ferror( file ) ) {
|
if ( file.error() ) {
|
||||||
// error reading
|
// error reading
|
||||||
(void)inflateEnd( &strm );
|
(void)inflateEnd( &strm );
|
||||||
/*successful = false;*/
|
/*successful = false;*/
|
||||||
|
@ -111,11 +157,7 @@ void readFile( const std::string& path, std::string& content )
|
||||||
// clean up and return
|
// clean up and return
|
||||||
(void)inflateEnd( &strm );
|
(void)inflateEnd( &strm );
|
||||||
successful = (ret == Z_STREAM_END) ? true : false;
|
successful = (ret == Z_STREAM_END) ? true : false;
|
||||||
if ( fclose( file ) ) {
|
file.close(); // throws GenericException on failure
|
||||||
// error while trying to close file pointer
|
|
||||||
throw GenericException( "Failed to close file pointer" );
|
|
||||||
}
|
|
||||||
//delete file;
|
|
||||||
}
|
}
|
||||||
if ( content.empty() ) {
|
if ( content.empty() ) {
|
||||||
// probably not a gzip compressed file
|
// probably not a gzip compressed file
|
||||||
|
|
|
@ -10,6 +10,49 @@
|
||||||
#include <fstream>
|
#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
|
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 )
|
void readFile( const std::string& path, std::string& content )
|
||||||
{
|
{
|
||||||
// read the whole file
|
// read the whole file
|
||||||
std::ifstream file;
|
|
||||||
try {
|
try {
|
||||||
/*constexpr std::size_t read_size = std::size_t(4096);*/
|
FileHandler<std::ifstream> file{ path }; // throws std::ios_base::failure on failure
|
||||||
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" );
|
|
||||||
}
|
|
||||||
// add bit exceptions
|
// add bit exceptions
|
||||||
file.exceptions( std::ifstream::failbit );
|
file.setException( std::ifstream::failbit );
|
||||||
file.exceptions( std::ios_base::badbit );
|
file.setException( std::ios_base::badbit );
|
||||||
// read the whole file
|
// read the whole file
|
||||||
content = std::string(
|
content = std::string(
|
||||||
std::istreambuf_iterator<char>( file ),
|
std::istreambuf_iterator<char>( *file ),
|
||||||
std::istreambuf_iterator<char>() );
|
std::istreambuf_iterator<char>() );
|
||||||
|
|
||||||
} catch ( const std::ios_base::failure& ) {
|
} catch ( const std::ios_base::failure& ) {
|
||||||
// failed reading
|
// failed reading
|
||||||
if ( file.is_open() ) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
throw;
|
throw;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if ( file.is_open() ) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
throw std::exception(); // already catched
|
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 )
|
void writeOnFile( const std::string& path, std::string_view content )
|
||||||
{
|
{
|
||||||
std::ofstream file;
|
|
||||||
try {
|
try {
|
||||||
file.open( path );
|
FileHandler<std::ofstream> file{ path }; // throws std::ios_base::failure on failure
|
||||||
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" );
|
|
||||||
}
|
|
||||||
// add bit exceptions
|
// add bit exceptions
|
||||||
file.exceptions( std::ifstream::failbit );
|
file.setException( std::ios_base::failbit );
|
||||||
file.exceptions( std::ios_base::badbit );
|
file.setException( std::ios_base::badbit );
|
||||||
// write the content
|
// write the content
|
||||||
file << content << std::endl;
|
*file << content << std::endl;
|
||||||
|
|
||||||
} catch ( const std::ios_base::failure& ) {
|
} catch ( const std::ios_base::failure& ) {
|
||||||
// failed writing
|
// failed writing
|
||||||
if ( file.is_open() ) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
throw;
|
throw;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if ( file.is_open() ) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
throw std::exception(); // already catched
|
throw std::exception(); // already catched
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( file.is_open() ) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace IOUtils
|
} // namespace IOUtils
|
||||||
|
|
Loading…
Reference in a new issue