forked from kiwix/kiwix-tools
parent
189d97b220
commit
3d44961ead
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
|
||||
* NON-INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZIM_LZMASTREAM_H
|
||||
#define ZIM_LZMASTREAM_H
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <lzma.h>
|
||||
#include <vector>
|
||||
|
||||
namespace zim
|
||||
{
|
||||
class LzmaError : public std::runtime_error
|
||||
{
|
||||
lzma_ret ret;
|
||||
|
||||
public:
|
||||
LzmaError(lzma_ret ret_, const std::string& msg)
|
||||
: std::runtime_error(msg),
|
||||
ret(ret_)
|
||||
{ }
|
||||
|
||||
lzma_ret getRetcode() const { return ret; }
|
||||
};
|
||||
|
||||
class LzmaStreamBuf : public std::streambuf
|
||||
{
|
||||
lzma_stream stream;
|
||||
std::vector<char_type> obuffer;
|
||||
std::streambuf* sink;
|
||||
|
||||
public:
|
||||
LzmaStreamBuf(std::streambuf* sink_,
|
||||
uint32_t preset = 3 | LZMA_PRESET_EXTREME,
|
||||
lzma_check check = LZMA_CHECK_CRC32 /* LZMA_CHECK_NONE */,
|
||||
unsigned bufsize = 8192);
|
||||
~LzmaStreamBuf();
|
||||
|
||||
/// see std::streambuf
|
||||
int_type overflow(int_type c);
|
||||
/// see std::streambuf
|
||||
int_type underflow();
|
||||
/// see std::streambuf
|
||||
int sync();
|
||||
/// end stream
|
||||
int end();
|
||||
|
||||
void setSink(std::streambuf* sink_) { sink = sink_; }
|
||||
};
|
||||
|
||||
class LzmaStream : public std::ostream
|
||||
{
|
||||
LzmaStreamBuf streambuf;
|
||||
|
||||
public:
|
||||
explicit LzmaStream(std::streambuf* sink,
|
||||
uint32_t preset = 3 | LZMA_PRESET_EXTREME,
|
||||
lzma_check check = LZMA_CHECK_CRC32 /* LZMA_CHECK_NONE */,
|
||||
unsigned bufsize = 8192)
|
||||
: std::ostream(0),
|
||||
streambuf(sink, preset, check, bufsize)
|
||||
{ init(&streambuf); }
|
||||
explicit LzmaStream(std::ostream& sink,
|
||||
uint32_t preset = 3 | LZMA_PRESET_EXTREME,
|
||||
lzma_check check = LZMA_CHECK_CRC32 /* LZMA_CHECK_NONE */,
|
||||
unsigned bufsize = 8192)
|
||||
: std::ostream(0),
|
||||
streambuf(sink.rdbuf(), preset, check, bufsize)
|
||||
{ init(&streambuf); }
|
||||
|
||||
void end();
|
||||
void setSink(std::streambuf* sink) { streambuf.setSink(sink); }
|
||||
void setSink(std::ostream& sink) { streambuf.setSink(sink.rdbuf()); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ZIM_LZMASTREAM_H
|
||||
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ZIM_UNLZMASTREAM_H
|
||||
#define ZIM_UNLZMASTREAM_H
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <lzma.h>
|
||||
|
||||
namespace zim
|
||||
{
|
||||
class UnlzmaError : public std::runtime_error
|
||||
{
|
||||
lzma_ret ret;
|
||||
|
||||
public:
|
||||
UnlzmaError(lzma_ret ret_, const std::string& msg)
|
||||
: std::runtime_error(msg),
|
||||
ret(ret_)
|
||||
{ }
|
||||
|
||||
lzma_ret getRetcode() const { return ret; }
|
||||
};
|
||||
|
||||
class UnlzmaStreamBuf : public std::streambuf
|
||||
{
|
||||
lzma_stream stream;
|
||||
char_type* iobuffer;
|
||||
unsigned bufsize;
|
||||
std::streambuf* sinksource;
|
||||
|
||||
char_type* ibuffer() { return iobuffer; }
|
||||
std::streamsize ibuffer_size() { return bufsize >> 1; }
|
||||
char_type* obuffer() { return iobuffer + ibuffer_size(); }
|
||||
std::streamsize obuffer_size() { return bufsize >> 1; }
|
||||
|
||||
public:
|
||||
explicit UnlzmaStreamBuf(std::streambuf* sinksource_, unsigned bufsize = 8192);
|
||||
~UnlzmaStreamBuf();
|
||||
|
||||
/// see std::streambuf
|
||||
int_type overflow(int_type c);
|
||||
/// see std::streambuf
|
||||
int_type underflow();
|
||||
/// see std::streambuf
|
||||
int sync();
|
||||
|
||||
void setSinksource(std::streambuf* sinksource_) { sinksource = sinksource_; }
|
||||
};
|
||||
|
||||
class UnlzmaStream : public std::iostream
|
||||
{
|
||||
UnlzmaStreamBuf streambuf;
|
||||
|
||||
public:
|
||||
explicit UnlzmaStream(std::streambuf* sinksource, unsigned bufsize = 8192)
|
||||
: std::iostream(0),
|
||||
streambuf(sinksource, bufsize)
|
||||
{ init(&streambuf); }
|
||||
explicit UnlzmaStream(std::ios& sinksource, unsigned bufsize = 8192)
|
||||
: std::iostream(0),
|
||||
streambuf(sinksource.rdbuf(), bufsize)
|
||||
{ init(&streambuf); }
|
||||
|
||||
void setSinksource(std::streambuf* sinksource) { streambuf.setSinksource(sinksource); }
|
||||
void setSinksource(std::ios& sinksource) { streambuf.setSinksource(sinksource.rdbuf()); }
|
||||
void setSink(std::ostream& sink) { streambuf.setSinksource(sink.rdbuf()); }
|
||||
void setSource(std::istream& source) { streambuf.setSinksource(source.rdbuf()); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ZIM_UNLZMASTREAM_H
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
/* src/zimlib/src/config.h. Generated from config.h.in by configure. */
|
||||
/* src/zimlib/src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* set zim cluster cache size to number of cached chunks */
|
||||
#define CLUSTER_CACHE_SIZE 16
|
||||
|
||||
/* set zim dirent cache size to number of cached chunks */
|
||||
#define DIRENT_CACHE_SIZE 51200
|
||||
|
||||
/* defined if bzip2 compression is enabled */
|
||||
#define ENABLE_BZIP2 1
|
||||
|
||||
/* defined if lzma compression is enabled */
|
||||
#define ENABLE_LZMA 1
|
||||
|
||||
/* defined if zlib compression is enabled */
|
||||
#define ENABLE_ZLIB 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `bz2' library (-lbz2). */
|
||||
#define HAVE_LIBBZ2 1
|
||||
|
||||
/* Define to 1 if you have the `lzma' library (-llzma). */
|
||||
#define HAVE_LIBLZMA 1
|
||||
|
||||
/* Define to 1 if you have the `microhttpd' library (-lmicrohttpd). */
|
||||
#define HAVE_LIBMICROHTTPD 1
|
||||
|
||||
/* Define to 1 if you have the `unac' library (-lunac). */
|
||||
#define HAVE_LIBUNAC 1
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#define HAVE_LIBZ 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `stat64' function. */
|
||||
#define HAVE_STAT64 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* set lzma uncompress memory size to number of MB */
|
||||
#define LZMA_MEMORY_SIZE 128
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "kiwix"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "kiwix"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "kiwix 0.9"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "kiwix"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.9"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.9"
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
|
||||
* NON-INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace zim
|
||||
{
|
||||
unsigned envValue(const char* env, unsigned def)
|
||||
{
|
||||
const char* v = ::getenv(env);
|
||||
if (v)
|
||||
{
|
||||
std::istringstream s(v);
|
||||
s >> def;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
unsigned envMemSize(const char* env, unsigned def)
|
||||
{
|
||||
const char* v = ::getenv(env);
|
||||
if (v)
|
||||
{
|
||||
char unit = '\0';
|
||||
std::istringstream s(v);
|
||||
s >> def >> unit;
|
||||
|
||||
switch (unit)
|
||||
{
|
||||
case 'k':
|
||||
case 'K': def *= 1024; break;
|
||||
case 'm':
|
||||
case 'M': def *= 1024 * 1024; break;
|
||||
case 'g':
|
||||
case 'G': def *= 1024 * 1024 * 1024; break;
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
|
||||
* NON-INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ZIM_ENVVALUE_H
|
||||
#define ZIM_ENVVALUE_H
|
||||
|
||||
namespace zim
|
||||
{
|
||||
unsigned envValue(const char* env, unsigned def);
|
||||
unsigned envMemSize(const char* env, unsigned def);
|
||||
}
|
||||
|
||||
#endif // ZIM_ENVVALUE_H
|
||||
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
|
||||
* NON-INFRINGEMENT. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <zim/lzmastream.h>
|
||||
#include "log.h"
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
log_define("zim.lzma.compress")
|
||||
|
||||
namespace zim
|
||||
{
|
||||
namespace
|
||||
{
|
||||
lzma_ret checkError(lzma_ret ret)
|
||||
{
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "lzma-error " << ret;
|
||||
switch (ret)
|
||||
{
|
||||
case LZMA_OK: msg << ": LZMA_OK"; break;
|
||||
case LZMA_STREAM_END: msg << ": LZMA_STREAM_END"; break;
|
||||
case LZMA_NO_CHECK: msg << ": LZMA_NO_CHECK"; break;
|
||||
case LZMA_UNSUPPORTED_CHECK: msg << ": LZMA_UNSUPPORTED_CHECK"; break;
|
||||
case LZMA_GET_CHECK: msg << ": LZMA_GET_CHECK"; break;
|
||||
case LZMA_MEM_ERROR: msg << ": LZMA_MEM_ERROR"; break;
|
||||
case LZMA_MEMLIMIT_ERROR: msg << ": LZMA_MEMLIMIT_ERROR"; break;
|
||||
case LZMA_FORMAT_ERROR: msg << ": LZMA_FORMAT_ERROR"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg << ": LZMA_OPTIONS_ERROR"; break;
|
||||
case LZMA_DATA_ERROR: msg << ": LZMA_DATA_ERROR"; break;
|
||||
case LZMA_BUF_ERROR: msg << ": LZMA_BUF_ERROR"; break;
|
||||
case LZMA_PROG_ERROR: msg << ": LZMA_PROG_ERROR"; break;
|
||||
}
|
||||
log_error(msg.str());
|
||||
throw LzmaError(ret, msg.str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
LzmaStreamBuf::LzmaStreamBuf(std::streambuf* sink_, uint32_t preset, lzma_check check, unsigned bufsize_)
|
||||
: obuffer(bufsize_),
|
||||
sink(sink_)
|
||||
{
|
||||
std::memset(reinterpret_cast<void*>(&stream), 0, sizeof(stream));
|
||||
|
||||
checkError(
|
||||
::lzma_easy_encoder(&stream, preset, check));
|
||||
|
||||
setp(&obuffer[0], &obuffer[0] + obuffer.size());
|
||||
}
|
||||
|
||||
LzmaStreamBuf::~LzmaStreamBuf()
|
||||
{
|
||||
::lzma_end(&stream);
|
||||
}
|
||||
|
||||
LzmaStreamBuf::int_type LzmaStreamBuf::overflow(int_type c)
|
||||
{
|
||||
// initialize input-stream
|
||||
stream.next_in = reinterpret_cast<const uint8_t*>(&obuffer[0]);
|
||||
stream.avail_in = pptr() - &obuffer[0];
|
||||
|
||||
// initialize zbuffer for compressed data
|
||||
char zbuffer[8192];
|
||||
stream.next_out = reinterpret_cast<uint8_t*>(zbuffer);
|
||||
stream.avail_out = sizeof(zbuffer);
|
||||
|
||||
// compress
|
||||
checkError(::lzma_code(&stream, LZMA_RUN));
|
||||
|
||||
// copy zbuffer to sink / consume deflated data
|
||||
std::streamsize count = sizeof(zbuffer) - stream.avail_out;
|
||||
if (count > 0)
|
||||
{
|
||||
std::streamsize n = sink->sputn(zbuffer, count);
|
||||
if (n < count)
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
// move remaining characters to start of obuffer
|
||||
if (stream.avail_in > 0)
|
||||
memmove(&obuffer[0], stream.next_in, stream.avail_in);
|
||||
|
||||
// reset outbuffer
|
||||
setp(&obuffer[0] + stream.avail_in, &obuffer[0] + obuffer.size());
|
||||
if (c != traits_type::eof())
|
||||
sputc(traits_type::to_char_type(c));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LzmaStreamBuf::int_type LzmaStreamBuf::underflow()
|
||||
{
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
int LzmaStreamBuf::sync()
|
||||
{
|
||||
// initialize input-stream for
|
||||
stream.next_in = reinterpret_cast<const uint8_t*>(&obuffer[0]);
|
||||
stream.avail_in = pptr() - pbase();
|
||||
char zbuffer[8192];
|
||||
while (stream.avail_in > 0)
|
||||
{
|
||||
// initialize zbuffer
|
||||
stream.next_out = (uint8_t*)zbuffer;
|
||||
stream.avail_out = sizeof(zbuffer);
|
||||
|
||||
checkError(::lzma_code(&stream, LZMA_FINISH));
|
||||
|
||||
// copy zbuffer to sink
|
||||
std::streamsize count = sizeof(zbuffer) - stream.avail_out;
|
||||
if (count > 0)
|
||||
{
|
||||
std::streamsize n = sink->sputn(zbuffer, count);
|
||||
if (n < count)
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
// reset outbuffer
|
||||
setp(&obuffer[0], &obuffer[0] + obuffer.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LzmaStreamBuf::end()
|
||||
{
|
||||
char zbuffer[8192];
|
||||
// initialize input-stream for
|
||||
stream.next_in = reinterpret_cast<const uint8_t*>(&obuffer[0]);
|
||||
stream.avail_in = pptr() - pbase();
|
||||
lzma_ret ret;
|
||||
do
|
||||
{
|
||||
// initialize zbuffer
|
||||
stream.next_out = (uint8_t*)zbuffer;
|
||||
stream.avail_out = sizeof(zbuffer);
|
||||
|
||||
ret = checkError(::lzma_code(&stream, LZMA_FINISH));
|
||||
|
||||
// copy zbuffer to sink
|
||||
std::streamsize count = sizeof(zbuffer) - stream.avail_out;
|
||||
if (count > 0)
|
||||
{
|
||||
std::streamsize n = sink->sputn(zbuffer, count);
|
||||
if (n < count)
|
||||
return -1;
|
||||
}
|
||||
} while (ret != LZMA_STREAM_END);
|
||||
|
||||
// reset outbuffer
|
||||
setp(&obuffer[0], &obuffer[0] + obuffer.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LzmaStream::end()
|
||||
{
|
||||
if (streambuf.end() != 0)
|
||||
setstate(failbit);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Tommi Maekitalo
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "zim/unlzmastream.h"
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include "envvalue.h"
|
||||
|
||||
log_define("zim.lzma.uncompress")
|
||||
|
||||
namespace zim
|
||||
{
|
||||
namespace
|
||||
{
|
||||
lzma_ret checkError(lzma_ret ret)
|
||||
{
|
||||
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "inflate-error " << ret;
|
||||
switch (ret)
|
||||
{
|
||||
case LZMA_OK: msg << ": LZMA_OK"; break;
|
||||
case LZMA_STREAM_END: msg << ": LZMA_STREAM_END"; break;
|
||||
case LZMA_NO_CHECK: msg << ": LZMA_NO_CHECK"; break;
|
||||
case LZMA_UNSUPPORTED_CHECK: msg << ": LZMA_UNSUPPORTED_CHECK"; break;
|
||||
case LZMA_GET_CHECK: msg << ": LZMA_GET_CHECK"; break;
|
||||
case LZMA_MEM_ERROR: msg << ": LZMA_MEM_ERROR"; break;
|
||||
case LZMA_MEMLIMIT_ERROR: msg << ": LZMA_MEMLIMIT_ERROR"; break;
|
||||
case LZMA_FORMAT_ERROR: msg << ": LZMA_FORMAT_ERROR"; break;
|
||||
case LZMA_OPTIONS_ERROR: msg << ": LZMA_OPTIONS_ERROR"; break;
|
||||
case LZMA_DATA_ERROR: msg << ": LZMA_DATA_ERROR"; break;
|
||||
case LZMA_BUF_ERROR: msg << ": LZMA_BUF_ERROR"; break;
|
||||
case LZMA_PROG_ERROR: msg << ": LZMA_PROG_ERROR"; break;
|
||||
}
|
||||
log_error(msg);
|
||||
throw UnlzmaError(ret, msg.str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UnlzmaStreamBuf::UnlzmaStreamBuf(std::streambuf* sinksource_, unsigned bufsize_)
|
||||
: iobuffer(new char_type[bufsize_]),
|
||||
bufsize(bufsize_),
|
||||
sinksource(sinksource_)
|
||||
{
|
||||
std::memset(reinterpret_cast<void*>(&stream), 0, sizeof(stream));
|
||||
|
||||
unsigned memsize = envMemSize("ZIM_LZMA_MEMORY_SIZE", LZMA_MEMORY_SIZE * 1024 * 1024);
|
||||
checkError(
|
||||
::lzma_stream_decoder(&stream, memsize, 0));
|
||||
}
|
||||
|
||||
UnlzmaStreamBuf::~UnlzmaStreamBuf()
|
||||
{
|
||||
::lzma_end(&stream);
|
||||
delete[] iobuffer;
|
||||
}
|
||||
|
||||
UnlzmaStreamBuf::int_type UnlzmaStreamBuf::overflow(int_type c)
|
||||
{
|
||||
if (pptr())
|
||||
{
|
||||
// initialize input-stream for
|
||||
stream.next_in = reinterpret_cast<const uint8_t*>(obuffer());
|
||||
stream.avail_in = pptr() - pbase();
|
||||
|
||||
lzma_ret ret;
|
||||
do
|
||||
{
|
||||
// initialize ibuffer
|
||||
stream.next_out = reinterpret_cast<uint8_t*>(ibuffer());
|
||||
stream.avail_out = ibuffer_size();
|
||||
|
||||
ret = ::lzma_code(&stream, LZMA_RUN);
|
||||
checkError(ret);
|
||||
|
||||
// copy zbuffer to sinksource
|
||||
std::streamsize count = ibuffer_size() - stream.avail_out;
|
||||
std::streamsize n = sinksource->sputn(reinterpret_cast<char*>(ibuffer()), count);
|
||||
if (n < count)
|
||||
return traits_type::eof();
|
||||
} while (ret != LZMA_STREAM_END && stream.avail_in > 0);
|
||||
}
|
||||
|
||||
// reset outbuffer
|
||||
setp(obuffer(), obuffer() + obuffer_size());
|
||||
if (c != traits_type::eof())
|
||||
sputc(traits_type::to_char_type(c));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UnlzmaStreamBuf::int_type UnlzmaStreamBuf::underflow()
|
||||
{
|
||||
// read from sinksource and decompress into obuffer
|
||||
|
||||
stream.next_out = reinterpret_cast<uint8_t*>(obuffer());
|
||||
stream.avail_out = obuffer_size();
|
||||
|
||||
do
|
||||
{
|
||||
// fill ibuffer first if needed
|
||||
if (stream.avail_in == 0)
|
||||
{
|
||||
if (sinksource->in_avail() > 0)
|
||||
{
|
||||
// there is data already available
|
||||
// read compressed data from source into ibuffer
|
||||
stream.avail_in = sinksource->sgetn(ibuffer(), std::min(sinksource->in_avail(), ibuffer_size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no data available
|
||||
stream.avail_in = sinksource->sgetn(ibuffer(), ibuffer_size());
|
||||
if (stream.avail_in == 0)
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
stream.next_in = (const uint8_t*)ibuffer();
|
||||
}
|
||||
|
||||
// we decompress it now into obuffer
|
||||
|
||||
// at least one character received from source - pass to decompressor
|
||||
|
||||
checkError(::lzma_code(&stream, LZMA_RUN));
|
||||
|
||||
setg(obuffer(), obuffer(), obuffer() + obuffer_size() - stream.avail_out);
|
||||
|
||||
} while (gptr() == egptr());
|
||||
|
||||
return sgetc();
|
||||
}
|
||||
|
||||
int UnlzmaStreamBuf::sync()
|
||||
{
|
||||
if (pptr() && overflow(traits_type::eof()) == traits_type::eof())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue