mirror of https://github.com/PurpleI2P/i2pd.git
hagen
9 years ago
9 changed files with 158 additions and 132 deletions
@ -0,0 +1,108 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2016, The PurpleI2P Project |
||||||
|
* |
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3 |
||||||
|
* |
||||||
|
* See full license text in LICENSE file at top of project tree |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <inttypes.h> |
||||||
|
#include <string.h> /* memset */ |
||||||
|
#include <iostream> |
||||||
|
|
||||||
|
#include "Gzip.h" |
||||||
|
|
||||||
|
namespace i2p { |
||||||
|
namespace data { |
||||||
|
const size_t GZIP_CHUNK_SIZE = 16384; |
||||||
|
|
||||||
|
GzipInflator::GzipInflator (): m_IsDirty (false) |
||||||
|
{ |
||||||
|
memset (&m_Inflator, 0, sizeof (m_Inflator)); |
||||||
|
inflateInit2 (&m_Inflator, MAX_WBITS + 16); // gzip
|
||||||
|
} |
||||||
|
|
||||||
|
GzipInflator::~GzipInflator () |
||||||
|
{ |
||||||
|
inflateEnd (&m_Inflator); |
||||||
|
} |
||||||
|
|
||||||
|
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen) |
||||||
|
{ |
||||||
|
if (m_IsDirty) inflateReset (&m_Inflator); |
||||||
|
m_IsDirty = true; |
||||||
|
m_Inflator.next_in = const_cast<uint8_t *>(in); |
||||||
|
m_Inflator.avail_in = inLen; |
||||||
|
m_Inflator.next_out = out; |
||||||
|
m_Inflator.avail_out = outLen; |
||||||
|
int err; |
||||||
|
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) { |
||||||
|
return outLen - m_Inflator.avail_out; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os) |
||||||
|
{ |
||||||
|
m_IsDirty = true; |
||||||
|
uint8_t * out = new uint8_t[GZIP_CHUNK_SIZE]; |
||||||
|
m_Inflator.next_in = const_cast<uint8_t *>(in); |
||||||
|
m_Inflator.avail_in = inLen; |
||||||
|
int ret; |
||||||
|
do { |
||||||
|
m_Inflator.next_out = out; |
||||||
|
m_Inflator.avail_out = GZIP_CHUNK_SIZE; |
||||||
|
ret = inflate (&m_Inflator, Z_NO_FLUSH); |
||||||
|
if (ret < 0) { |
||||||
|
inflateEnd (&m_Inflator); |
||||||
|
os.setstate(std::ios_base::failbit); |
||||||
|
break; |
||||||
|
} |
||||||
|
os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out); |
||||||
|
} while (!m_Inflator.avail_out); // more data to read
|
||||||
|
delete[] out; |
||||||
|
} |
||||||
|
|
||||||
|
void GzipInflator::Inflate (std::istream& in, std::ostream& out) |
||||||
|
{ |
||||||
|
uint8_t * buf = new uint8_t[GZIP_CHUNK_SIZE]; |
||||||
|
while (!in.eof ()) |
||||||
|
{ |
||||||
|
in.read ((char *) buf, GZIP_CHUNK_SIZE); |
||||||
|
Inflate (buf, in.gcount (), out); |
||||||
|
} |
||||||
|
delete[] buf; |
||||||
|
} |
||||||
|
|
||||||
|
GzipDeflator::GzipDeflator (): m_IsDirty (false) |
||||||
|
{ |
||||||
|
memset (&m_Deflator, 0, sizeof (m_Deflator)); |
||||||
|
deflateInit2 (&m_Deflator, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); // 15 + 16 sets gzip
|
||||||
|
} |
||||||
|
|
||||||
|
GzipDeflator::~GzipDeflator () |
||||||
|
{ |
||||||
|
deflateEnd (&m_Deflator); |
||||||
|
} |
||||||
|
|
||||||
|
void GzipDeflator::SetCompressionLevel (int level) |
||||||
|
{ |
||||||
|
deflateParams (&m_Deflator, level, Z_DEFAULT_STRATEGY); |
||||||
|
} |
||||||
|
|
||||||
|
size_t GzipDeflator::Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen) |
||||||
|
{ |
||||||
|
if (m_IsDirty) deflateReset (&m_Deflator); |
||||||
|
m_IsDirty = true; |
||||||
|
m_Deflator.next_in = const_cast<uint8_t *>(in); |
||||||
|
m_Deflator.avail_in = inLen; |
||||||
|
m_Deflator.next_out = out; |
||||||
|
m_Deflator.avail_out = outLen; |
||||||
|
int err; |
||||||
|
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) { |
||||||
|
return outLen - m_Deflator.avail_out; |
||||||
|
} /* else */ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} // data
|
||||||
|
} // i2p
|
@ -0,0 +1,44 @@ |
|||||||
|
#ifndef GZIP_H__ |
||||||
|
#define GZIP_H__ |
||||||
|
|
||||||
|
#include <zlib.h> |
||||||
|
|
||||||
|
namespace i2p { |
||||||
|
namespace data { |
||||||
|
class GzipInflator |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
GzipInflator (); |
||||||
|
~GzipInflator (); |
||||||
|
|
||||||
|
size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen); |
||||||
|
/** @note @a os failbit will be set in case of error */ |
||||||
|
void Inflate (const uint8_t * in, size_t inLen, std::ostream& os); |
||||||
|
void Inflate (std::istream& in, std::ostream& out); |
||||||
|
|
||||||
|
private: |
||||||
|
|
||||||
|
z_stream m_Inflator; |
||||||
|
bool m_IsDirty; |
||||||
|
}; |
||||||
|
|
||||||
|
class GzipDeflator |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
GzipDeflator (); |
||||||
|
~GzipDeflator (); |
||||||
|
|
||||||
|
void SetCompressionLevel (int level); |
||||||
|
size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen); |
||||||
|
|
||||||
|
private: |
||||||
|
|
||||||
|
z_stream m_Deflator; |
||||||
|
bool m_IsDirty; |
||||||
|
}; |
||||||
|
} // data
|
||||||
|
} // i2p
|
||||||
|
|
||||||
|
#endif /* GZIP_H__ */ |
Loading…
Reference in new issue