diff options
author | Perttu Ahola <celeron55@gmail.com> | 2010-12-13 21:32:35 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2010-12-13 21:32:35 +0200 |
commit | 3ac2abb0b5f84819abe6feea9d7b883b40369610 (patch) | |
tree | 2fad297e30cdae1b205d77dc559b25d9e5a0efc7 /src/serialization.cpp | |
parent | 22037459e321cfe51719c58f492145d39b48c196 (diff) | |
download | minetest-3ac2abb0b5f84819abe6feea9d7b883b40369610.tar.gz minetest-3ac2abb0b5f84819abe6feea9d7b883b40369610.tar.bz2 minetest-3ac2abb0b5f84819abe6feea9d7b883b40369610.zip |
commit before content-tile separation
Diffstat (limited to 'src/serialization.cpp')
-rw-r--r-- | src/serialization.cpp | 182 |
1 files changed, 177 insertions, 5 deletions
diff --git a/src/serialization.cpp b/src/serialization.cpp index 57db2b40f..eb80f3c60 100644 --- a/src/serialization.cpp +++ b/src/serialization.cpp @@ -17,18 +17,184 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* -(c) 2010 Perttu Ahola <celeron55@gmail.com> -*/ - #include "serialization.h" #include "utility.h" +#include "zlib.h" + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zerr: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + break; + default: + dstream<<"return value = "<<ret<<"\n"; + } +} + +void compressZlib(SharedBuffer<u8> data, std::ostream &os) +{ + z_stream z; + const s32 bufsize = 16384; + //char input_buffer[bufsize]; + char output_buffer[bufsize]; + int input_i = 0; + int status = 0; + int ret; + + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + ret = deflateInit(&z, -1); + if(ret != Z_OK) + throw SerializationError("compressZlib: deflateInit failed"); + + z.avail_in = 0; + + for(;;) + { + int flush = Z_NO_FLUSH; + z.next_out = (Bytef*)output_buffer; + z.avail_out = bufsize; + + if(z.avail_in == 0) + { + //z.next_in = (char*)&data[input_i]; + z.next_in = (Bytef*)&data[input_i]; + z.avail_in = data.getSize() - input_i; + input_i += z.avail_in; + if(input_i == (int)data.getSize()) + flush = Z_FINISH; + } + if(z.avail_in == 0) + break; + status = deflate(&z, flush); + if(status == Z_NEED_DICT || status == Z_DATA_ERROR + || status == Z_MEM_ERROR) + { + zerr(status); + throw SerializationError("compressZlib: deflate failed"); + } + int count = bufsize - z.avail_out; + if(count) + os.write(output_buffer, count); + } + + deflateEnd(&z); + +} + +void decompressZlib(std::istream &is, std::ostream &os) +{ + z_stream z; + const s32 bufsize = 16384; + char input_buffer[bufsize]; + char output_buffer[bufsize]; + int status = 0; + int ret; + int bytes_read = 0; + int input_buffer_len = 0; + + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + ret = inflateInit(&z); + if(ret != Z_OK) + throw SerializationError("compressZlib: inflateInit failed"); + + z.avail_in = 0; + + //dstream<<"initial fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; + + for(;;) + { + z.next_out = (Bytef*)output_buffer; + z.avail_out = bufsize; + + if(z.avail_in == 0) + { + z.next_in = (Bytef*)input_buffer; + input_buffer_len = is.readsome(input_buffer, bufsize); + z.avail_in = input_buffer_len; + //dstream<<"read fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; + } + if(z.avail_in == 0) + { + //dstream<<"z.avail_in == 0"<<std::endl; + break; + } + + //dstream<<"1 z.avail_in="<<z.avail_in<<std::endl; + status = inflate(&z, Z_NO_FLUSH); + //dstream<<"2 z.avail_in="<<z.avail_in<<std::endl; + bytes_read += is.gcount() - z.avail_in; + //dstream<<"bytes_read="<<bytes_read<<std::endl; + + if(status == Z_NEED_DICT || status == Z_DATA_ERROR + || status == Z_MEM_ERROR) + { + zerr(status); + throw SerializationError("compressZlib: inflate failed"); + } + int count = bufsize - z.avail_out; + //dstream<<"count="<<count<<std::endl; + if(count) + os.write(output_buffer, count); + if(status == Z_STREAM_END) + { + //dstream<<"Z_STREAM_END"<<std::endl; + + //dstream<<"z.avail_in="<<z.avail_in<<std::endl; + //dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; + // Unget all the data that inflate didn't take + for(u32 i=0; i < z.avail_in; i++) + { + is.unget(); + if(is.fail() || is.bad()) + { + dstream<<"unget #"<<i<<" failed"<<std::endl; + dstream<<"fail="<<is.fail()<<" bad="<<is.bad()<<std::endl; + throw SerializationError("compressZlib: unget failed"); + } + } + + break; + } + } + + inflateEnd(&z); +} void compress(SharedBuffer<u8> data, std::ostream &os, u8 version) { - if(data.getSize() == 0) + if(version >= 11) + { + compressZlib(data, os); return; + } + if(data.getSize() == 0) + return; + // Write length (u32) u8 tmp[4]; @@ -63,6 +229,12 @@ void compress(SharedBuffer<u8> data, std::ostream &os, u8 version) void decompress(std::istream &is, std::ostream &os, u8 version) { + if(version >= 11) + { + decompressZlib(is, os); + return; + } + // Read length (u32) u8 tmp[4]; |