Subversion Repositories Scribus

Rev

Rev 11809 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8022 jghali 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
 
11801 jghali 8
#include <cstdio>
11746 cbradney 9
#include <cstdlib>
8022 jghali 10
#include <zlib.h>
11212 jghali 11
#include <QDir>
9968 fschmid 12
#include <QFileInfo>
8022 jghali 13
 
14
#include "scconfig.h"
15
#include "scgzfile.h"
16
 
11739 jghali 17
const  int ScGzFile::gzipExpansionFactor = 8;
18
 
11801 jghali 19
struct  ScGzFileDataPrivate
8022 jghali 20
{
11801 jghali 21
        FILE*  file;
22
        gzFile gzfile;
11739 jghali 23
};
24
 
11801 jghali 25
ScGzFile::ScGzFile(const QString& fileName) : QIODevice(), m_fileName(fileName)
11739 jghali 26
{
11801 jghali 27
        m_fileName = fileName;
28
        m_data     = NULL;
8022 jghali 29
}
30
 
11739 jghali 31
ScGzFile::~ScGzFile(void)
8022 jghali 32
{
11801 jghali 33
        freeData();
8022 jghali 34
}
35
 
11801 jghali 36
int ScGzFile::error(void) const
8022 jghali 37
{
11801 jghali 38
        int errCode = 0;
39
        if (m_data)
40
                gzerror(m_data->gzfile, &errCode);
41
        return errCode;
42
}
43
 
44
bool ScGzFile::errorOccurred(void) const
45
{
46
        bool errorOccurred = false;
47
        if (m_data)
11739 jghali 48
        {
11801 jghali 49
                int errCode = error();
50
                errorOccurred = (errCode != Z_OK && errCode != Z_STREAM_END);
11739 jghali 51
        }
11801 jghali 52
        return errorOccurred;
11739 jghali 53
}
54
 
11801 jghali 55
ScGzFileDataPrivate* ScGzFile::newPrivateData(void)
11739 jghali 56
{
11801 jghali 57
        freeData();
58
        m_data = (ScGzFileDataPrivate*) malloc(sizeof(ScGzFileDataPrivate));
59
        if (m_data)
11739 jghali 60
        {
11801 jghali 61
                m_data->file   = NULL;
62
                m_data->gzfile = NULL;
63
        }
64
        return m_data;
65
}
11739 jghali 66
 
11801 jghali 67
void ScGzFile::freeData(void)
68
{
69
        if (m_data)
70
        {
71
                free(m_data);
72
                m_data = NULL;
11739 jghali 73
        }
74
}
75
 
11801 jghali 76
bool ScGzFile::gzFileOpen(QString fileName, ScGzFileDataPrivate* data, QIODevice::OpenMode mode)
11739 jghali 77
{
11801 jghali 78
        bool success = false;
79
        FILE* file   = NULL;
80
        gzFile gzf   = NULL;
81
        QString localPath = QDir::toNativeSeparators(fileName);
82
#if defined(_WIN32)
83
        if (mode == QIODevice::ReadOnly)
84
                file = _wfopen((const wchar_t*) localPath.utf16(), L"rb");
85
        else if (mode == QIODevice::WriteOnly)
86
                file = _wfopen((const wchar_t*) localPath.utf16(), L"wb");
87
        if (file)
11739 jghali 88
        {
11801 jghali 89
                int fno = _fileno(file);
90
                gzf = gzdopen(fno,(mode == QIODevice::ReadOnly) ? "rb" : "wb");
91
                if (!gzf) fclose(file);
11739 jghali 92
        }
11801 jghali 93
#else
94
        if (mode == QIODevice::ReadOnly)
95
                file = fopen(localPath.toLocal8Bit().data(), "rb");
96
        else if (mode == QIODevice::WriteOnly)
97
                file = fopen(localPath.toLocal8Bit().data(), "wb");
98
        if (file)
99
        {
100
                int fno = fileno(file);
101
                gzf = gzdopen(fno,(mode == QIODevice::ReadOnly) ? "rb" : "wb");
102
                if (!gzf) fclose(file);
103
        }
104
#endif
105
        if (gzf)
106
        {
107
                data->file   = file;
108
                data->gzfile = gzf;
109
                success = true;
110
        }
111
        return success;
11739 jghali 112
}
113
 
114
bool ScGzFile::open(QIODevice::OpenMode mode)
115
{
11801 jghali 116
        bool success = true;
117
        if (isOpen()) return false;
11739 jghali 118
 
11801 jghali 119
        freeData();
120
        if (mode == QIODevice::ReadOnly || mode == QIODevice::WriteOnly)
121
                m_data = newPrivateData();
122
        if (!m_data) return false;
11739 jghali 123
 
11801 jghali 124
        bool opened = gzFileOpen(m_fileName, m_data, mode);
11739 jghali 125
        if (opened)
126
        {
11801 jghali 127
                opened &= QIODevice::open(mode);
128
                if (!opened)
129
                        this->close();
130
                success = opened;
11739 jghali 131
        }
11801 jghali 132
        return success;
11739 jghali 133
}
134
 
11801 jghali 135
bool ScGzFile::reset(void)
11739 jghali 136
{
11801 jghali 137
        if (!m_data || (openMode() != QIODevice::ReadOnly))
11739 jghali 138
                return false;
139
 
11801 jghali 140
        int res = gzrewind(m_data->gzfile);
141
        QIODevice::reset();
142
        return (res == 0);
143
}
11739 jghali 144
 
12788 jghali 145
bool ScGzFile::atEnd() const
11801 jghali 146
{
147
        if (m_data)
148
        {
149
                if (openMode() == QIODevice::ReadOnly)
150
                {
151
                        int result = gzeof(m_data->gzfile);
152
                        return result;
153
                }
154
                return QIODevice::atEnd();
155
        }
156
        return QIODevice::atEnd();
157
}
11739 jghali 158
 
11801 jghali 159
qint64 ScGzFile::readData (char * data, qint64 maxSize)
160
{
161
        if (!m_data || (openMode() != QIODevice::ReadOnly))
162
                return 0;
163
 
164
        int result = gzread(m_data->gzfile, data, maxSize);
165
        return result;
11739 jghali 166
}
167
 
11801 jghali 168
qint64 ScGzFile::writeData (const char * data, qint64 dataLen)
11739 jghali 169
{
11801 jghali 170
        if (!m_data || (openMode() != QIODevice::WriteOnly))
171
                return false;
11739 jghali 172
 
11801 jghali 173
    int result = gzwrite(m_data->gzfile, data, dataLen);
174
        return result;
11739 jghali 175
}
176
 
177
void ScGzFile::close()
178
{
11801 jghali 179
        if (!isOpen() || !m_data)
11739 jghali 180
                return;
181
 
11801 jghali 182
        gzclose(m_data->gzfile);
183
        QIODevice::close();
184
        freeData();
11739 jghali 185
}
186
 
187
bool ScGzFile::readFromFile(const QString& filename, QByteArray& bArray, uint maxBytes)
188
{
8022 jghali 189
        int i;
8109 fschmid 190
        uint maxB = 0xFFFFFFFF;
191
        if (maxBytes != 0)
192
                maxB = maxBytes;
11739 jghali 193
        bArray.resize(0);
11803 jghali 194
        ScGzFile gzFile(filename);
195
        if(!gzFile.open(QIODevice::ReadOnly))
8022 jghali 196
        {
197
                return false; // FIXME: Needs better error return
198
        }
199
        // Allocate a buffer of a multiple of the compressed size of the file
200
        // as a starting point for loading. We'll expand this buffer by powers
201
        // of two if we run out of space.
11739 jghali 202
        const QFileInfo fi(filename);
8579 jghali 203
        uint bufSize = qMin<uint>(4096, fi.size()*gzipExpansionFactor);
11739 jghali 204
        bArray.resize(bufSize);
205
        char* buf = bArray.data();
8022 jghali 206
        uint bytesRead = 0;
207
        // While there's free space, read into the buffer....
11803 jghali 208
        while ((i = gzFile.read(buf,bufSize-bytesRead-1)) > 0)
8022 jghali 209
        {
210
                // Ensure the string is null-terminated and move the
211
                // write pointer to the current position.
212
                buf[i]=0;
213
                buf+=i;
214
                bytesRead += i;
215
                // And check that there's free space to work with, expanding the
216
                // buffer if there's not.
217
                if (bufSize - bytesRead < 4096)
218
                {
219
                        bufSize *= 2;
11739 jghali 220
                        bArray.resize(bufSize);
221
                        buf = bArray.data() + bytesRead;
8022 jghali 222
                }
8109 fschmid 223
                if (maxB >= 0 && bytesRead >= maxB)
8022 jghali 224
                        break;
225
        }
11803 jghali 226
        gzFile.close();
11739 jghali 227
        return (bArray.size() > 0);
8022 jghali 228
}
229
 
11752 jghali 230
bool ScGzFile::writeToFile(const QString& filename, const QByteArray& bArray)
8022 jghali 231
{
11803 jghali 232
        ScGzFile gzFile(filename);
233
        if (gzFile.open(QIODevice::WriteOnly))
11212 jghali 234
        {
11803 jghali 235
                int res = gzFile.write(bArray.data(), bArray.size());
236
                gzFile.close();
11739 jghali 237
                return (res > 0 && (res == bArray.size()));
11212 jghali 238
        }
239
        return false;
8022 jghali 240
}
241
 
11752 jghali 242
bool ScGzFile::writeToFile(const QString& filename, const QByteArray& bArray, const char* header)
8022 jghali 243
{
11803 jghali 244
        ScGzFile gzFile(filename);
245
        if(gzFile.open(QIODevice::WriteOnly))
11212 jghali 246
        {
11803 jghali 247
                int res1 = gzFile.write(header, strlen(header));
248
                int res2 = gzFile.write(bArray.data(), bArray.size());
249
                gzFile.close();
11229 fschmid 250
                bool done1 = (res1 > 0 && (res1 == static_cast<int>(strlen(header))));
11739 jghali 251
                bool done2 = (res2 > 0 && (res2 == bArray.size()));
11212 jghali 252
                return (done1 && done2);
253
        }
254
        return false;
8022 jghali 255
}