2012-02-20 21:47:14 +00:00
|
|
|
/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
|
2009-01-28 20:55:45 +00:00
|
|
|
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
|
|
|
|
|
|
|
|
#include "file.hh"
|
2023-04-14 10:50:00 +00:00
|
|
|
#include "fsencoding.hh"
|
|
|
|
#include "zipfile.hh"
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2012-01-30 13:11:41 +00:00
|
|
|
#include <string>
|
2023-04-14 10:50:00 +00:00
|
|
|
#include <QFileInfo>
|
2011-09-09 12:05:28 +00:00
|
|
|
#ifdef __WIN32
|
2023-04-14 10:50:00 +00:00
|
|
|
#include <windows.h>
|
2011-09-09 12:05:28 +00:00
|
|
|
#endif
|
|
|
|
|
2009-01-28 20:55:45 +00:00
|
|
|
namespace File {
|
|
|
|
|
2012-01-30 13:11:41 +00:00
|
|
|
bool tryPossibleName( std::string const & name, std::string & copyTo )
|
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
if ( File::exists( name ) ) {
|
2012-01-30 13:11:41 +00:00
|
|
|
copyTo = name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-04-24 14:42:01 +00:00
|
|
|
bool tryPossibleZipName( std::string const & name, std::string & copyTo )
|
|
|
|
{
|
2023-04-13 10:08:32 +00:00
|
|
|
if ( ZipFile::SplitZipFile( name.c_str() ).exists() ) {
|
2017-04-24 14:42:01 +00:00
|
|
|
copyTo = name;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void loadFromFile( std::string const & filename, std::vector< char > & data )
|
2012-01-30 13:11:41 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
File::Class f( filename, "rb" );
|
|
|
|
QByteArray byteArray{ f.readall() };
|
|
|
|
data.reserve( byteArray.size() );
|
|
|
|
data = std::vector< char >( byteArray.cbegin(), byteArray.cend() );
|
2009-05-17 22:22:10 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::open( char const * mode )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2014-02-26 14:22:12 +00:00
|
|
|
QFile::OpenMode openMode = QIODevice::Text;
|
2023-04-14 10:50:00 +00:00
|
|
|
|
2014-02-26 14:22:12 +00:00
|
|
|
const char * pch = mode;
|
2023-04-14 10:50:00 +00:00
|
|
|
while ( *pch ) {
|
|
|
|
switch ( *pch ) {
|
|
|
|
case 'r':
|
|
|
|
openMode |= QIODevice::ReadOnly;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
openMode |= QIODevice::WriteOnly;
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
openMode &= ~( QIODevice::ReadOnly | QIODevice::WriteOnly );
|
|
|
|
openMode |= QIODevice::ReadWrite;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
openMode |= QIODevice::Append;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
openMode &= ~QIODevice::Text;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2014-02-26 14:22:12 +00:00
|
|
|
}
|
|
|
|
++pch;
|
|
|
|
}
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2014-02-26 14:22:12 +00:00
|
|
|
if ( !f.open( openMode ) )
|
2023-04-14 10:50:00 +00:00
|
|
|
throw exCantOpen( f.fileName().toStdString() + ": " + f.errorString().toUtf8().data() );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
Class::Class( std::string_view filename, char const * mode )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
f.setFileName( QString::fromUtf8( filename.data(), filename.size() ) );
|
|
|
|
open( mode );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::read( void * buf, qint64 size )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
qint64 result = f.read( static_cast< char * >( buf ), size );
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2014-02-26 14:22:12 +00:00
|
|
|
if ( result != size )
|
2009-01-28 20:55:45 +00:00
|
|
|
throw exReadError();
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
size_t Class::readRecords( void * buf, qint64 size, qint64 count )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
qint64 result = f.read( static_cast< char * >( buf ), size * count );
|
2014-02-26 14:22:12 +00:00
|
|
|
return result < 0 ? result : result / size;
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::write( void const * buf, qint64 size )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
if ( 0 == size ) {
|
2009-01-28 20:55:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
if ( size < 0 ) {
|
|
|
|
throw exWriteError();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
f.write( static_cast< char const * >( buf ), size );
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
size_t Class::writeRecords( void const * buf, qint64 size, qint64 count )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
qint64 result = f.write( static_cast< const char * >( buf ), size * count );
|
2014-02-26 14:22:12 +00:00
|
|
|
return result < 0 ? result : result / size;
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char * Class::gets( char * s, int size, bool stripNl )
|
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
qint64 len = f.readLine( s, size );
|
|
|
|
char * result = len > 0 ? s : nullptr;
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
if ( result && stripNl ) {
|
2009-01-28 20:55:45 +00:00
|
|
|
|
|
|
|
char * last = result + len;
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
while ( len-- ) {
|
2009-01-28 20:55:45 +00:00
|
|
|
--last;
|
|
|
|
|
|
|
|
if ( *last == '\n' || *last == '\r' )
|
|
|
|
*last = 0;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
std::string Class::gets( bool stripNl )
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
char buf[ 1024 ];
|
|
|
|
|
|
|
|
if ( !gets( buf, sizeof( buf ), stripNl ) )
|
|
|
|
throw exReadError();
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
return { buf };
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
QByteArray Class::readall()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
return f.readAll();
|
|
|
|
};
|
2009-01-28 20:55:45 +00:00
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
|
|
|
|
void Class::seek( qint64 offset )
|
|
|
|
{
|
2014-02-26 14:22:12 +00:00
|
|
|
if ( !f.seek( offset ) )
|
2009-01-28 20:55:45 +00:00
|
|
|
throw exSeekError();
|
|
|
|
}
|
|
|
|
|
2022-06-13 14:12:03 +00:00
|
|
|
uchar * Class::map( qint64 offset, qint64 size )
|
|
|
|
{
|
|
|
|
return f.map( offset, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Class::unmap( uchar * address )
|
|
|
|
{
|
|
|
|
return f.unmap( address );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::seekEnd()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
if ( !f.seek( f.size() ) )
|
2009-01-28 20:55:45 +00:00
|
|
|
throw exSeekError();
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::rewind()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
seek( 0 );
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
qint64 Class::tell()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
return f.pos();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
bool Class::eof() const
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2014-02-26 14:22:12 +00:00
|
|
|
return f.atEnd();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
QFile & Class::file()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
void Class::close()
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2014-02-26 14:22:12 +00:00
|
|
|
f.close();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
2022-06-03 13:28:41 +00:00
|
|
|
Class::~Class() noexcept
|
2009-01-28 20:55:45 +00:00
|
|
|
{
|
2023-04-14 10:50:00 +00:00
|
|
|
f.close();
|
2009-01-28 20:55:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-04-14 10:50:00 +00:00
|
|
|
} // namespace File
|