00001 #include <zlib.h>
00002 #include <sys/stat.h>
00003 #include <iostream>
00004 #include "mrs/message.h"
00005 #include "Sct/StdExceptionWrapper.h"
00006 #include "ZlibStringCompressor.h"
00007 #include "ZlibException.h"
00008 using std::string;
00009
00010 namespace SctArchiving{
00011
00012 ZlibStringCompressor::ZlibStringCompressor(unsigned long bufferSize)
00013 : m_bufferSize(0), m_buffer(0), m_debugLevel(0) {
00014 if (bufferSize) setBufferSize(bufferSize);
00015 }
00016
00017 unsigned long ZlibStringCompressor::getBufferSize(){
00018 return m_bufferSize;
00019 }
00020
00021 Bytef* ZlibStringCompressor::setBufferSize(const unsigned long size){
00022 delete m_buffer;
00023 if (getDebugLevel()>0) std::cout << "Deleted buffer" << std::endl;
00024 m_bufferSize=0;
00025 try {
00026 m_buffer = new Bytef[size];
00027 } catch (std::bad_alloc&){
00028 throw ZlibException("Caught std::bad_alloc", __FILE__, __LINE__);
00029 }
00030 if (getDebugLevel()>0) std::cout << "Set buffer size to " << size << std::endl;
00031 m_bufferSize=size;
00032 return m_buffer;
00033 }
00034
00035 void ZlibStringCompressor::checkZlibResult(const int result, const char* file, const int line){
00036 switch (result) {
00037 case (Z_OK) : { break;}
00038 case (Z_MEM_ERROR) : { throw ZlibException("zlib reports memory error", file, line);}
00039 case (Z_BUF_ERROR) : { throw ZlibException("zlib buffer insufficient", file, line);}
00040 case (Z_STREAM_ERROR) : { throw ZlibException("zlib reports stream error", file, line);}
00041 case (Z_DATA_ERROR) : { throw ZlibException("zlib reports data corrupted error", file, line);}
00042 default : {
00043 std::ostringstream oss;
00044 oss << "zlib returned the unknown value of `" << result << "'";
00045 throw ZlibException(oss.str(), file, line);
00046 }
00047 }
00048 }
00049
00050 const string ZlibStringCompressor::compress(const string& s_in, int level){
00051
00052 unsigned long required_length=findRequiredBufferSize(findSizeInBytes(s_in));
00053
00054 if ( required_length>getBufferSize() ) {
00055 setBufferSize( required_length*2 );
00056 }
00057
00058
00059 const char* input_char = s_in.c_str();
00060 const Bytef* input_bytes = reinterpret_cast<const Bytef*> ( input_char );
00061
00062
00063 int checked_level = (level<1) ? 1 : (level>9) ? 9 : level;
00064
00065 unsigned long output_length = getBufferSize();
00066 int result = compress2 (m_buffer, &output_length, input_bytes,
00067 findSizeInBytes(s_in), checked_level);
00068
00069 checkZlibResult(result, __FILE__, __LINE__);
00070 const char* result_char=reinterpret_cast<const char*>(m_buffer);
00071 unsigned long char_length=output_length/sizeof(char);
00072 const string s_out(result_char, char_length);
00073 return s_out;
00074 }
00075
00076 const string ZlibStringCompressor::inflate(const string& s){
00077 long unsigned compressed_length=findSizeInBytes(s);
00078 if (compressed_length*10 > getBufferSize() ){
00079 setBufferSize(compressed_length*10);
00080 }
00081
00082 long unsigned inflated_length=0;
00083 const char* compressed_c_str=s.c_str();
00084 const Bytef* compressed_bytes=reinterpret_cast<const Bytef*>(compressed_c_str);
00085
00086 int result = Z_OK;
00087 do {
00088 inflated_length=getBufferSize();
00089 result = uncompress (m_buffer, &inflated_length, compressed_bytes, findSizeInBytes(s));
00090 if (result==Z_BUF_ERROR) setBufferSize(getBufferSize()*2);
00091 } while (result==Z_BUF_ERROR);
00092
00093 checkZlibResult(result,__FILE__,__LINE__);
00094
00095 unsigned long inflated_char_length=inflated_length/sizeof(char);
00096 const string s_inflated((char*)m_buffer, inflated_char_length);
00097
00098 return s_inflated;
00099 }
00100
00101 }