00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00031 #include "lzfu.h"
00032
00033 #include <QtCore/QIODevice>
00034
00035 #include <sys/types.h>
00036 #include <string.h>
00037 #include <stdio.h>
00038
00039
00040
00041
00042 #define LZFU_COMPRESSED 0x75465a4c
00043 #define LZFU_UNCOMPRESSED 0x414c454d
00044
00045 #define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
00046 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
00047 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
00048 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
00049 "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
00050 "\\tx"
00051 #define LZFU_INITLENGTH 207
00052
00053
00054
00055 typedef struct _lzfuheader
00056 {
00057 quint32 cbSize;
00058 quint32 cbRawSize;
00059 quint32 dwMagic;
00060 quint32 dwCRC;
00061 } lzfuheader;
00062
00063
00064
00065 #define FLAG(f,n) (f>>n)&0x1
00066
00067
00068
00069
00070
00071
00072 #define OFFSET(b) (b>>4)&0xFFF
00073 #define LENGTH(b) ((b&0xF)+2)
00074
00075
00076 int lzfu_decompress( QIODevice *input, QIODevice *output )
00077 {
00078 unsigned char window[4096];
00079 unsigned int wlength = 0, cursor = 0, ocursor = 0;
00080 lzfuheader lzfuhdr;
00081
00082 quint16 blkhdr;
00083 char bFlags;
00084 int nFlags;
00085
00086 memcpy( window, LZFU_INITDICT, LZFU_INITLENGTH );
00087 wlength = LZFU_INITLENGTH;
00088 if ( input->read( (char *)&lzfuhdr, sizeof(lzfuhdr) ) != sizeof(lzfuhdr) ) {
00089 fprintf( stderr, "unexpected eof, cannot read LZFU header\n" );
00090 return -1;
00091 }
00092 cursor += sizeof( lzfuhdr );
00093 #ifdef DO_DEBUG
00094 fprintf( stdout, "total size : %d\n", lzfuhdr.cbSize+4 );
00095 fprintf( stdout, "raw size : %d\n", lzfuhdr.cbRawSize );
00096 fprintf( stdout, "compressed : %s\n", ( lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no" ) );
00097 fprintf( stdout, "CRC : %x\n", lzfuhdr.dwCRC );
00098 fprintf( stdout, "\n" );
00099 #endif
00100
00101 while ( cursor < lzfuhdr.cbSize+4 && ocursor < lzfuhdr.cbRawSize && !input->atEnd() ) {
00102 if ( input->read( &bFlags, 1 ) != 1 ) {
00103 fprintf( stderr, "unexpected eof, cannot read chunk flag\n" );
00104 return -1;
00105 }
00106 nFlags = 8;
00107 cursor++;
00108 #ifdef DO_DEBUG
00109 fprintf( stdout, "Flags : " );
00110 for ( int i=nFlags-1; i>=0; i-- ) {
00111 fprintf( stdout, "%d", FLAG( bFlags, i ) );
00112 }
00113 fprintf( stdout, "\n" );
00114 #endif
00115 for ( int i=0; i<nFlags && ocursor<lzfuhdr.cbRawSize && cursor<lzfuhdr.cbSize+4; i++ ) {
00116 if ( FLAG( bFlags, i ) ) {
00117
00118 char c1, c2;
00119 if ( input->read( &c1, 1 ) != 1 || input->read( &c2, 1 ) != 1 ) {
00120 fprintf( stderr, "unexpected eof, cannot read block header\n" );
00121 return -1;
00122 }
00123 blkhdr = c1;
00124 blkhdr <<= 8;
00125 blkhdr |= ( 0xFF & c2 );
00126 unsigned int offset = OFFSET( blkhdr ), length = LENGTH( blkhdr );
00127 cursor += 2;
00128 #ifdef DO_DEBUG
00129 fprintf( stdout, "block : offset=%.4d [%d], length=%.2d (0x%04X)\n",
00130 OFFSET( blkhdr ), wlength, LENGTH( blkhdr ), blkhdr );
00131 #endif
00132
00133
00134
00135 #ifdef DO_DEBUG
00136 fprintf( stdout, "block : " );
00137 #endif
00138 for ( unsigned int i=0; i<length; i++ ) {
00139 c1 = window[( offset + i ) % 4096];
00140
00141 window[wlength] = c1;
00142 wlength = ( wlength + 1 ) % 4096;
00143
00144 #ifdef DO_DEBUG
00145 if ( c1 == '\n' ) {
00146 fprintf( stdout, "\nblock : " );
00147 } else {
00148 fprintf( stdout, "%c", c1 );
00149 }
00150 #endif
00151 output->putChar( c1 );
00152 ocursor++;
00153 }
00154 #ifdef DO_DEBUG
00155 fprintf( stdout, "\n" );
00156 #endif
00157 } else {
00158
00159 char c;
00160 if ( !input->getChar( &c ) ) {
00161 if ( !input->atEnd() ) {
00162 fprintf( stderr, "unexpected eof, cannot read character\n" );
00163 return -1;
00164 }
00165 break;
00166 }
00167 #ifdef DO_DEBUG
00168 fprintf( stdout, "char : %c\n", c );
00169 #endif
00170 cursor++;
00171
00172 window[wlength] = c;
00173 wlength = ( wlength+1 ) % 4096;
00174
00175 output->putChar( c );
00176 ocursor++;
00177 }
00178 }
00179
00180 }
00181
00182 return 0;
00183 }