annotate data/fileio/BZipFileDevice.cpp @ 316:3a6725f285d6

* Make RemoteFile far more pervasive, and use it for local files as well so that we can handle both transparently. Make it shallow copy with reference counting, so it can be used by value without having to worry about the cache file lifetime. Use RemoteFile for MainWindow file-open functions, etc
author Chris Cannam
date Thu, 18 Oct 2007 15:31:20 +0000
parents 8ee6cf529c4e
children b4a8d8221eaf
rev   line source
Chris@148 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@148 2
Chris@148 3 /*
Chris@148 4 Sonic Visualiser
Chris@148 5 An audio file viewer and annotation editor.
Chris@148 6 Centre for Digital Music, Queen Mary, University of London.
Chris@148 7 This file copyright 2006 Chris Cannam.
Chris@148 8
Chris@148 9 This program is free software; you can redistribute it and/or
Chris@148 10 modify it under the terms of the GNU General Public License as
Chris@148 11 published by the Free Software Foundation; either version 2 of the
Chris@148 12 License, or (at your option) any later version. See the file
Chris@148 13 COPYING included with this distribution for more information.
Chris@148 14 */
Chris@148 15
Chris@148 16 #include "BZipFileDevice.h"
Chris@148 17
Chris@148 18 #include <bzlib.h>
Chris@148 19
Chris@148 20 #include <iostream>
Chris@148 21
Chris@148 22 BZipFileDevice::BZipFileDevice(QString fileName) :
Chris@148 23 m_fileName(fileName),
Chris@148 24 m_file(0),
Chris@148 25 m_bzFile(0),
Chris@207 26 m_atEnd(true),
Chris@207 27 m_ok(true)
Chris@148 28 {
Chris@148 29 }
Chris@148 30
Chris@148 31 BZipFileDevice::~BZipFileDevice()
Chris@148 32 {
Chris@148 33 // std::cerr << "BZipFileDevice::~BZipFileDevice(" << m_fileName.toStdString() << ")" << std::endl;
Chris@148 34 if (m_bzFile) close();
Chris@148 35 }
Chris@148 36
Chris@148 37 bool
Chris@207 38 BZipFileDevice::isOK() const
Chris@207 39 {
Chris@207 40 return m_ok;
Chris@207 41 }
Chris@207 42
Chris@207 43 bool
Chris@148 44 BZipFileDevice::open(OpenMode mode)
Chris@148 45 {
Chris@203 46 setErrorString("");
Chris@203 47
Chris@148 48 if (m_bzFile) {
Chris@148 49 setErrorString(tr("File is already open"));
Chris@148 50 return false;
Chris@148 51 }
Chris@148 52
Chris@148 53 if (mode & Append) {
Chris@148 54 setErrorString(tr("Append mode not supported"));
Chris@207 55 m_ok = false;
Chris@148 56 return false;
Chris@148 57 }
Chris@148 58
Chris@148 59 if ((mode & (ReadOnly | WriteOnly)) == 0) {
Chris@148 60 setErrorString(tr("File access mode not specified"));
Chris@207 61 m_ok = false;
Chris@148 62 return false;
Chris@148 63 }
Chris@148 64
Chris@148 65 if ((mode & ReadOnly) && (mode & WriteOnly)) {
Chris@148 66 setErrorString(tr("Read and write modes both specified"));
Chris@207 67 m_ok = false;
Chris@148 68 return false;
Chris@148 69 }
Chris@148 70
Chris@148 71 if (mode & WriteOnly) {
Chris@148 72
Chris@148 73 m_file = fopen(m_fileName.toLocal8Bit().data(), "wb");
Chris@148 74 if (!m_file) {
Chris@148 75 setErrorString(tr("Failed to open file for writing"));
Chris@207 76 m_ok = false;
Chris@148 77 return false;
Chris@148 78 }
Chris@148 79
Chris@148 80 int bzError = BZ_OK;
Chris@148 81 m_bzFile = BZ2_bzWriteOpen(&bzError, m_file, 9, 0, 0);
Chris@148 82
Chris@148 83 if (!m_bzFile) {
Chris@148 84 fclose(m_file);
Chris@148 85 m_file = 0;
Chris@148 86 setErrorString(tr("Failed to open bzip2 stream for writing"));
Chris@207 87 m_ok = false;
Chris@148 88 return false;
Chris@148 89 }
Chris@148 90
Chris@148 91 // std::cerr << "BZipFileDevice: opened \"" << m_fileName.toStdString() << "\" for writing" << std::endl;
Chris@148 92
Chris@148 93 setErrorString(QString());
Chris@148 94 setOpenMode(mode);
Chris@148 95 return true;
Chris@148 96 }
Chris@148 97
Chris@148 98 if (mode & ReadOnly) {
Chris@148 99
Chris@148 100 m_file = fopen(m_fileName.toLocal8Bit().data(), "rb");
Chris@148 101 if (!m_file) {
Chris@148 102 setErrorString(tr("Failed to open file for reading"));
Chris@207 103 m_ok = false;
Chris@148 104 return false;
Chris@148 105 }
Chris@148 106
Chris@148 107 int bzError = BZ_OK;
Chris@148 108 m_bzFile = BZ2_bzReadOpen(&bzError, m_file, 0, 0, NULL, 0);
Chris@148 109
Chris@148 110 if (!m_bzFile) {
Chris@148 111 fclose(m_file);
Chris@148 112 m_file = 0;
Chris@148 113 setErrorString(tr("Failed to open bzip2 stream for reading"));
Chris@207 114 m_ok = false;
Chris@148 115 return false;
Chris@148 116 }
Chris@148 117
Chris@148 118 // std::cerr << "BZipFileDevice: opened \"" << m_fileName.toStdString() << "\" for reading" << std::endl;
Chris@148 119
Chris@148 120 m_atEnd = false;
Chris@148 121
Chris@148 122 setErrorString(QString());
Chris@148 123 setOpenMode(mode);
Chris@148 124 return true;
Chris@148 125 }
Chris@148 126
Chris@148 127 setErrorString(tr("Internal error (open for neither read nor write)"));
Chris@207 128 m_ok = false;
Chris@148 129 return false;
Chris@148 130 }
Chris@148 131
Chris@148 132 void
Chris@148 133 BZipFileDevice::close()
Chris@148 134 {
Chris@148 135 if (!m_bzFile) {
Chris@148 136 setErrorString(tr("File not open"));
Chris@207 137 m_ok = false;
Chris@148 138 return;
Chris@148 139 }
Chris@148 140
Chris@148 141 int bzError = BZ_OK;
Chris@148 142
Chris@148 143 if (openMode() & WriteOnly) {
Chris@148 144 unsigned int in = 0, out = 0;
Chris@148 145 BZ2_bzWriteClose(&bzError, m_bzFile, 0, &in, &out);
Chris@148 146 // std::cerr << "Wrote bzip2 stream (in=" << in << ", out=" << out << ")" << std::endl;
Chris@148 147 if (bzError != BZ_OK) {
Chris@148 148 setErrorString(tr("bzip2 stream write close error"));
Chris@148 149 }
Chris@148 150 fclose(m_file);
Chris@148 151 m_bzFile = 0;
Chris@148 152 m_file = 0;
Chris@207 153 m_ok = false;
Chris@148 154 return;
Chris@148 155 }
Chris@148 156
Chris@148 157 if (openMode() & ReadOnly) {
Chris@148 158 BZ2_bzReadClose(&bzError, m_bzFile);
Chris@148 159 if (bzError != BZ_OK) {
Chris@148 160 setErrorString(tr("bzip2 stream read close error"));
Chris@148 161 }
Chris@148 162 fclose(m_file);
Chris@148 163 m_bzFile = 0;
Chris@148 164 m_file = 0;
Chris@207 165 m_ok = false;
Chris@148 166 return;
Chris@148 167 }
Chris@148 168
Chris@148 169 setErrorString(tr("Internal error (close for neither read nor write)"));
Chris@148 170 return;
Chris@148 171 }
Chris@148 172
Chris@148 173 qint64
Chris@148 174 BZipFileDevice::readData(char *data, qint64 maxSize)
Chris@148 175 {
Chris@148 176 if (m_atEnd) return 0;
Chris@148 177
Chris@148 178 int bzError = BZ_OK;
Chris@148 179 int read = BZ2_bzRead(&bzError, m_bzFile, data, maxSize);
Chris@148 180
Chris@148 181 // std::cerr << "BZipFileDevice::readData: requested " << maxSize << ", read " << read << std::endl;
Chris@148 182
Chris@148 183 if (bzError != BZ_OK) {
Chris@148 184 if (bzError != BZ_STREAM_END) {
Chris@148 185 std::cerr << "BZipFileDevice::readData: error condition" << std::endl;
Chris@148 186 setErrorString(tr("bzip2 stream read error"));
Chris@207 187 m_ok = false;
Chris@148 188 return -1;
Chris@148 189 } else {
Chris@148 190 // std::cerr << "BZipFileDevice::readData: reached end of file" << std::endl;
Chris@148 191 m_atEnd = true;
Chris@148 192 }
Chris@148 193 }
Chris@148 194
Chris@148 195 return read;
Chris@148 196 }
Chris@148 197
Chris@148 198 qint64
Chris@148 199 BZipFileDevice::writeData(const char *data, qint64 maxSize)
Chris@148 200 {
Chris@148 201 int bzError = BZ_OK;
Chris@148 202 BZ2_bzWrite(&bzError, m_bzFile, (void *)data, maxSize);
Chris@148 203
Chris@148 204 // std::cerr << "BZipFileDevice::writeData: " << maxSize << " to write" << std::endl;
Chris@148 205
Chris@148 206 if (bzError != BZ_OK) {
Chris@148 207 std::cerr << "BZipFileDevice::writeData: error condition" << std::endl;
Chris@148 208 setErrorString("bzip2 stream write error");
Chris@207 209 m_ok = false;
Chris@148 210 return -1;
Chris@148 211 }
Chris@148 212
Chris@148 213 // std::cerr << "BZipFileDevice::writeData: wrote " << maxSize << std::endl;
Chris@148 214
Chris@148 215 return maxSize;
Chris@148 216 }
Chris@148 217