• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

strigi/src/streams

gzipinputstream.cpp

Go to the documentation of this file.
00001 /* This file is part of Strigi Desktop Search
00002  *
00003  * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 #include "gzipinputstream.h"
00021 #include <strigi/strigiconfig.h>
00022 #include <zlib.h>
00023 #include <stdlib.h>
00024 
00025 using namespace Strigi;
00026 
00027 class GZipInputStream::Private {
00028 public:
00029     GZipInputStream* const p;
00030     InputStream* input;
00031     z_stream_s* zstream;
00032 
00033     Private(GZipInputStream* gi, InputStream* input, ZipFormat format);
00034     ~Private();
00035     void dealloc();
00036     void readFromStream();
00037     void decompressFromStream();
00038     bool checkMagic();
00039 };
00040 GZipInputStream::GZipInputStream(InputStream* input, ZipFormat format)
00041         :p(new Private(this, input, format)) {
00042 }
00043 GZipInputStream::Private::Private(GZipInputStream* gi,
00044         InputStream* i, ZipFormat format) :p(gi), input(i), zstream(0) {
00045     // initialize values that signal state
00046     p->m_status = Ok;
00047 
00048     // check first bytes of stream before allocating buffer
00049     if (format == GZIPFORMAT && !checkMagic()) {
00050         p->m_error = "Magic bytes for gz are wrong.";
00051         p->m_status = Error;
00052         return;
00053     }
00054 
00055     // initialize the z_stream
00056     zstream = (z_stream_s*)malloc(sizeof(z_stream_s));
00057     zstream->zalloc = Z_NULL;
00058     zstream->zfree = Z_NULL;
00059     zstream->opaque = Z_NULL;
00060     zstream->avail_in = 0;
00061     zstream->next_in = Z_NULL;
00062     // initialize for reading gzip streams
00063     // for reading libz streams, you need inflateInit(zstream)
00064     int r;
00065     switch(format) {
00066     case ZLIBFORMAT:
00067         r = inflateInit(zstream);
00068         break;
00069     case GZIPFORMAT:
00070         r = inflateInit2(zstream, 15+16);
00071         break;
00072     case ZIPFORMAT:
00073     default:
00074         r = inflateInit2(zstream, -MAX_WBITS);
00075         break;
00076     }
00077     if (r != Z_OK) {
00078         p->m_error = "Error initializing GZipInputStream.";
00079         dealloc();
00080         p->m_status = Error;
00081         return;
00082     }
00083 
00084     // signal that we need to read into the buffer
00085     zstream->avail_out = 1;
00086 
00087     // initialize the buffer
00088     p->setMinBufSize(262144);
00089 }
00090 GZipInputStream::~GZipInputStream() {
00091     delete p;
00092 }
00093 GZipInputStream::Private::~Private() {
00094     dealloc();
00095 }
00096 void
00097 GZipInputStream::Private::dealloc() {
00098     if (zstream) {
00099         inflateEnd(zstream);
00100         free(zstream);
00101         zstream = 0;
00102     }
00103 }
00104 bool
00105 GZipInputStream::Private::checkMagic() {
00106     const unsigned char* buf;
00107     const char* begin;
00108     int32_t nread;
00109 
00110     int64_t pos = input->position();
00111     nread = input->read(begin, 2, 2);
00112     input->reset(pos);
00113     if (nread != 2) {
00114         return false;
00115     }
00116 
00117     buf = (const unsigned char*)begin;
00118     return buf[0] == 0x1f && buf[1] == 0x8b;
00119 }
00120 void
00121 GZipInputStream::Private::readFromStream() {
00122     // read data from the input stream
00123     const char* inStart;
00124     int32_t nread;
00125     nread = input->read(inStart, 1, 0);
00126     if (nread < -1) {
00127         p->m_status = Error;
00128         p->m_error = input->error();
00129     } else if (nread < 1) {
00130         p->m_status = Error;
00131         p->m_error.assign("unexpected end of stream");
00132     } else {
00133         zstream->next_in = (Bytef*)inStart;
00134         zstream->avail_in = nread;
00135     }
00136 }
00137 int32_t
00138 GZipInputStream::fillBuffer(char* start, int32_t space) {
00139     z_stream_s* zstream = p->zstream;
00140     if (zstream == 0) return -1;
00141     // make sure there is data to decompress
00142     if (zstream->avail_out) {
00143         p->readFromStream();
00144         if (m_status == Error) {
00145             // no data was read
00146             return -1;
00147         }
00148     }
00149     // make sure we can write into the buffer
00150     zstream->avail_out = space;
00151     zstream->next_out = (Bytef*)start;
00152     // decompress
00153     int r = inflate(zstream, Z_SYNC_FLUSH);
00154     // inform the buffer of the number of bytes that was read
00155     int32_t nwritten = space - zstream->avail_out;
00156     switch (r) {
00157     case Z_NEED_DICT:
00158         m_error.assign("Z_NEED_DICT while inflating stream.");
00159         m_status = Error;
00160         break;
00161     case Z_DATA_ERROR:
00162         m_error.assign("Z_DATA_ERROR while inflating stream.");
00163         m_status = Error;
00164         break;
00165     case Z_MEM_ERROR:
00166         m_error.assign("Z_MEM_ERROR while inflating stream.");
00167         m_status = Error;
00168         break;
00169     case Z_STREAM_END:
00170         if (zstream->avail_in) {
00171             p->input->reset(p->input->position()-zstream->avail_in);
00172         }
00173         // we are finished decompressing,
00174         // (but this stream is not yet finished)
00175         p->dealloc();
00176     }
00177     return nwritten;
00178 }

strigi/src/streams

Skip menu "strigi/src/streams"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal