1 /* This file is (c) 2017 Abs62
2  * Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
3 
4 #include "splitfile.hh"
5 #include "fsencoding.hh"
6 
7 namespace SplitFile
8 {
9 
SplitFile()10 SplitFile::SplitFile() :
11   currentFile( 0 )
12 {
13 }
14 
~SplitFile()15 SplitFile::~SplitFile()
16 {
17   close();
18 }
19 
appendFile(const QString & name)20 void SplitFile::appendFile( const QString & name )
21 {
22   if( offsets.isEmpty() )
23     offsets.append( 0 );
24   else
25     offsets.append( offsets.last() + files.last()->size() );
26   files.append( new QFile( name ) );
27 }
28 
close()29 void SplitFile::close()
30 {
31   for( QVector< QFile * >::const_iterator i = files.begin(); i != files.end(); ++i )
32   {
33     (*i)->close();
34     delete (*i);
35   }
36 
37   files.clear();
38   offsets.clear();
39 
40   currentFile = 0;
41 }
42 
getFilenames(vector<string> & names) const43 void SplitFile::getFilenames( vector< string > &names ) const
44 {
45   for( QVector< QFile const * >::const_iterator i = files.begin(); i != files.end(); ++i )
46     names.push_back( FsEncoding::encode( (*i)->fileName() ) );
47 }
48 
open(QFile::OpenMode mode)49 bool SplitFile::open( QFile::OpenMode mode )
50 {
51   for( QVector< QFile * >::iterator i = files.begin(); i != files.end(); ++i )
52     if( !(*i)->open( mode ) )
53     {
54       close();
55       return false;
56     }
57 
58   return true;
59 }
60 
seek(quint64 pos)61 bool SplitFile::seek( quint64 pos )
62 {
63   if( offsets.isEmpty() )
64     return false;
65 
66   int fileNom;
67 
68   for( fileNom = 0; fileNom < offsets.size() - 1; fileNom++ )
69     if( pos < offsets.at( fileNom + 1 ) )
70       break;
71 
72   pos -= offsets.at( fileNom );
73 
74   currentFile = fileNom;
75   return files.at( fileNom )->seek( pos );
76 }
77 
read(char * data,qint64 maxSize)78 qint64 SplitFile::read( char *data, qint64 maxSize )
79 {
80   if( offsets.isEmpty() )
81     return 0;
82 
83   quint64 bytesReaded = 0;
84   for( int i = currentFile; i < files.size(); i++ )
85   {
86     if( i != currentFile )
87     {
88       files.at( i )->seek( 0 );
89       currentFile = i;
90     }
91 
92     qint64 ret = files.at( i )->read( data + bytesReaded, maxSize );
93     if( ret < 0 )
94       break;
95 
96     bytesReaded += ret;
97     maxSize -= ret;
98 
99     if( maxSize <= 0 )
100       break;
101   }
102   return bytesReaded;
103 }
104 
read(qint64 maxSize)105 QByteArray SplitFile::read( qint64 maxSize )
106 {
107   QByteArray data;
108   data.resize( maxSize );
109 
110   qint64 ret = read( data.data(), maxSize );
111 
112   if( ret != maxSize )
113     data.resize( ret );
114 
115   return data;
116 }
117 
getChar(char * c)118 bool SplitFile::getChar( char *c )
119 {
120   char ch;
121   return read( c ? c : &ch, 1 ) == 1;
122 }
123 
pos() const124 qint64 SplitFile::pos() const
125 {
126   if( offsets.isEmpty() )
127     return 0;
128 
129   return offsets.at( currentFile ) + files.at( currentFile )->pos();
130 }
131 
132 } // namespace SplitFile
133