svcore  1.9
BZipFileDevice.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "BZipFileDevice.h"
00017 
00018 #include <bzlib.h>
00019 
00020 #include <iostream>
00021 
00022 #include "base/Debug.h"
00023 
00024 BZipFileDevice::BZipFileDevice(QString fileName) :
00025     m_fileName(fileName),
00026     m_file(0),
00027     m_bzFile(0),
00028     m_atEnd(true),
00029     m_ok(true)
00030 {
00031 }
00032 
00033 BZipFileDevice::~BZipFileDevice()
00034 {
00035 //    SVDEBUG << "BZipFileDevice::~BZipFileDevice(" << m_fileName << ")" << endl;
00036     if (m_bzFile) close();
00037 }
00038 
00039 bool
00040 BZipFileDevice::isOK() const
00041 {
00042     return m_ok;
00043 }
00044 
00045 bool
00046 BZipFileDevice::open(OpenMode mode)
00047 {
00048     setErrorString("");
00049 
00050     if (m_bzFile) {
00051         setErrorString(tr("File is already open"));
00052         return false;
00053     }
00054 
00055     if (mode & Append) {
00056         setErrorString(tr("Append mode not supported"));
00057         m_ok = false;
00058         return false;
00059     }
00060 
00061     if ((mode & (ReadOnly | WriteOnly)) == 0) {
00062         setErrorString(tr("File access mode not specified"));
00063         m_ok = false;
00064         return false;
00065     }
00066 
00067     if ((mode & ReadOnly) && (mode & WriteOnly)) {
00068         setErrorString(tr("Read and write modes both specified"));
00069         m_ok = false;
00070         return false;
00071     }
00072 
00073     if (mode & WriteOnly) {
00074 
00075         m_file = fopen(m_fileName.toLocal8Bit().data(), "wb");
00076         if (!m_file) {
00077             setErrorString(tr("Failed to open file for writing"));
00078             m_ok = false;
00079             return false;
00080         }
00081 
00082         int bzError = BZ_OK;
00083         m_bzFile = BZ2_bzWriteOpen(&bzError, m_file, 9, 0, 0);
00084 
00085         if (!m_bzFile) {
00086             fclose(m_file);
00087             m_file = 0;
00088             setErrorString(tr("Failed to open bzip2 stream for writing"));
00089             m_ok = false;
00090             return false;
00091         }
00092 
00093 //        cerr << "BZipFileDevice: opened \"" << m_fileName << "\" for writing" << endl;
00094 
00095         setErrorString(QString());
00096         setOpenMode(mode);
00097         return true;
00098     }
00099 
00100     if (mode & ReadOnly) {
00101 
00102         m_file = fopen(m_fileName.toLocal8Bit().data(), "rb");
00103         if (!m_file) {
00104             setErrorString(tr("Failed to open file for reading"));
00105             m_ok = false;
00106             return false;
00107         }
00108 
00109         int bzError = BZ_OK;
00110         m_bzFile = BZ2_bzReadOpen(&bzError, m_file, 0, 0, NULL, 0);
00111 
00112         if (!m_bzFile) {
00113             fclose(m_file);
00114             m_file = 0;
00115             setErrorString(tr("Failed to open bzip2 stream for reading"));
00116             m_ok = false;
00117             return false;
00118         }
00119 
00120 //        cerr << "BZipFileDevice: opened \"" << m_fileName << "\" for reading" << endl;
00121 
00122         m_atEnd = false;
00123 
00124         setErrorString(QString());
00125         setOpenMode(mode);
00126         return true;
00127     }
00128 
00129     setErrorString(tr("Internal error (open for neither read nor write)"));
00130     m_ok = false;
00131     return false;
00132 }
00133 
00134 void
00135 BZipFileDevice::close()
00136 {
00137     if (!m_bzFile) {
00138         setErrorString(tr("File not open"));
00139         m_ok = false;
00140         return;
00141     }
00142 
00143     int bzError = BZ_OK;
00144 
00145     if (openMode() & WriteOnly) {
00146         unsigned int in = 0, out = 0;
00147         BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out);
00148 //      cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << endl;
00149         if (bzError != BZ_OK) {
00150             setErrorString(tr("bzip2 stream write close error"));
00151         }
00152         fclose(m_file);
00153         m_bzFile = 0;
00154         m_file = 0;
00155         m_ok = false;
00156         return;
00157     }
00158 
00159     if (openMode() & ReadOnly) {
00160         BZ2_bzReadClose(&bzError, m_bzFile);
00161         if (bzError != BZ_OK) {
00162             setErrorString(tr("bzip2 stream read close error"));
00163         }
00164         fclose(m_file);
00165         m_bzFile = 0;
00166         m_file = 0;
00167         m_ok = false;
00168         return;
00169     }
00170 
00171     setErrorString(tr("Internal error (close for neither read nor write)"));
00172     return;
00173 }
00174 
00175 qint64
00176 BZipFileDevice::readData(char *data, qint64 maxSize)
00177 {
00178     if (m_atEnd) return 0;
00179 
00180     int bzError = BZ_OK;
00181     int read = BZ2_bzRead(&bzError, m_bzFile, data, maxSize);
00182 
00183 //    SVDEBUG << "BZipFileDevice::readData: requested " << maxSize << ", read " << read << endl;
00184 
00185     if (bzError != BZ_OK) {
00186         if (bzError != BZ_STREAM_END) {
00187             cerr << "BZipFileDevice::readData: error condition" << endl;
00188             setErrorString(tr("bzip2 stream read error"));
00189             m_ok = false;
00190             return -1;
00191         } else {
00192 //            SVDEBUG << "BZipFileDevice::readData: reached end of file" << endl;
00193             m_atEnd = true;
00194         }            
00195     }
00196 
00197     return read;
00198 }
00199 
00200 qint64
00201 BZipFileDevice::writeData(const char *data, qint64 maxSize)
00202 {
00203     int bzError = BZ_OK;
00204     BZ2_bzWrite(&bzError, m_bzFile, (void *)data, maxSize);
00205 
00206 //    SVDEBUG << "BZipFileDevice::writeData: " << maxSize << " to write" << endl;
00207 
00208     if (bzError != BZ_OK) {
00209         cerr << "BZipFileDevice::writeData: error condition" << endl;
00210         setErrorString("bzip2 stream write error");
00211         m_ok = false;
00212         return -1;
00213     }
00214 
00215 //    SVDEBUG << "BZipFileDevice::writeData: wrote " << maxSize << endl;
00216 
00217     return maxSize;
00218 }
00219