00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "cstream.h"
00022 #include "htdebug.h"
00023 #include "htendian.h"
00024 #include "minilzo.h"
00025 #include "tools.h"
00026
00027 #include <string.h>
00028
00029 void ht_compressed_stream::init(ht_stream *stream, bool own_stream, UINT granularity)
00030 {
00031 ht_layer_stream::init(stream, own_stream);
00032 if ((get_access_mode() & (FAM_READ | FAM_WRITE)) == (FAM_READ | FAM_WRITE)) {
00033
00034 assert(0);
00035 }
00036 buffer = (byte *)smalloc(granularity);
00037 bufferpos = 0;
00038 buffersize = granularity;
00039 }
00040
00041 void ht_compressed_stream::done()
00042 {
00043 if (get_access_mode() & FAM_WRITE) {
00044 flush_compressed();
00045 }
00046 if (buffer) free(buffer);
00047 ht_layer_stream::done();
00048 }
00049
00050 bool ht_compressed_stream::flush_compressed()
00051 {
00052 if (bufferpos) {
00053 byte *cbuf = (byte *)smalloc(bufferpos + bufferpos / 64 + 16 + 3);
00054 byte *workbuf = (byte *)smalloc(LZO1X_1_MEM_COMPRESS);
00055 lzo_uint cbuf_len;
00056 byte n[4];
00057
00058 lzo1x_1_compress(buffer, bufferpos, cbuf, &cbuf_len, workbuf);
00059
00060 free(workbuf);
00061
00062 create_foreign_int(n, bufferpos, 4, big_endian);
00063 if (stream->write(n, 4)!=4) {
00064 free(cbuf);
00065 return false;
00066 }
00067 create_foreign_int(n, cbuf_len, 4, big_endian);
00068 if (stream->write(n, 4)!=4) {
00069 free(cbuf);
00070 return false;
00071 }
00072 if (stream->write(cbuf, cbuf_len)!=cbuf_len) {
00073 free(cbuf);
00074 return false;
00075 }
00076
00077 free(cbuf);
00078
00079 bufferpos = 0;
00080 }
00081 return true;
00082 }
00083
00084 bool ht_compressed_stream::flush_uncompressed()
00085 {
00086 if (bufferpos==0) {
00087 free(buffer);
00088 buffer = NULL;
00089
00090 UINT cbuf_len;
00091 UINT uncompressed_len;
00092 byte n[4];
00093
00094 if (stream->read(n, 4)!=4) return false;
00095 uncompressed_len = create_host_int(n, 4, big_endian);
00096 if (stream->read(n, 4)!=4) return false;
00097 cbuf_len = create_host_int(n, 4, big_endian);
00098
00099 buffer = (byte *)smalloc(uncompressed_len);
00100 byte *cbuf = (byte *)smalloc(cbuf_len);
00101 if (stream->read(cbuf, cbuf_len)!=cbuf_len) {
00102 free(cbuf);
00103 return false;
00104 }
00105
00106 lzo_uint dummy;
00107 lzo1x_decompress(cbuf, cbuf_len, buffer, &dummy, NULL);
00108 assert(dummy == uncompressed_len);
00109
00110 free(cbuf);
00111
00112 buffersize = uncompressed_len;
00113 bufferpos = uncompressed_len;
00114 }
00115 return true;
00116 }
00117
00118 UINT ht_compressed_stream::read(void *aBuf, UINT size)
00119 {
00120 UINT ssize = size;
00121 byte *buf = (byte *)aBuf;
00122 while (size >= bufferpos) {
00123 memcpy(buf, buffer+buffersize-bufferpos, bufferpos);
00124 buf += bufferpos;
00125 size -= bufferpos;
00126 bufferpos = 0;
00127 if (size) {
00128 if (!flush_uncompressed()) return ssize - size;
00129 } else break;
00130 }
00131 if (size) {
00132 memcpy(buf, buffer+buffersize-bufferpos, size);
00133 bufferpos -= size;
00134 }
00135 return ssize;
00136 }
00137
00138 UINT ht_compressed_stream::write(const void *aBuf, UINT size)
00139 {
00140 UINT ssize = size;
00141 const byte *buf = (const byte *)aBuf;
00142 while (bufferpos+size >= buffersize) {
00143 memcpy(buffer+bufferpos, buf, buffersize-bufferpos);
00144 size -= buffersize-bufferpos;
00145 buf += buffersize-bufferpos;
00146 bufferpos = buffersize;
00147 if (size) {
00148 if (!flush_compressed()) return ssize - size;
00149 } else break;
00150 }
00151 if (size) {
00152 memcpy(buffer+bufferpos, buf, size);
00153 bufferpos += size;
00154 }
00155 return ssize;
00156 }