sample-deflate.c
1
2 #include <stdio.h>
3 #include <string.h>
4 #include <zlib.h>
5
6
7
8 #define IN_BUFSIZE 4096
9 #define OUT_BUFSIZE 4096
10
11
12
13 typedef struct Cio
14 {
15 const char *in_path;
16 const char *out_path;
17 FILE *in;
18 FILE *out;
19
20 z_stream z;
21
22 char in_buf[ IN_BUFSIZE ];
23 char out_buf[ OUT_BUFSIZE ];
24 } Cio, *hCio;
25
26
27
28 static void Cio_ZError( hCio h, const char *msg )
29 {
30 if ( msg != NULL )
31 fprintf( stderr, "%s: ", msg );
32 fprintf( stderr, "%s\n", h->z.msg );
33 }
34
35
36
37 static int Cio_Open( hCio h, const char *in_path, const char *out_path )
38 {
39
40 memset( h, 0, sizeof( *h ) );
41
42
43 h->in_path = in_path;
44 h->out_path = out_path;
45
46 if ( ( h->in = fopen( in_path, "rb" ) ) == NULL )
47 {
48
49 perror( in_path );
50 h->out = NULL;
51 return -1;
52 }
53 else if ( ( h->out = fopen( out_path, "wb" ) ) == NULL )
54 {
55
56 perror( out_path );
57 h->in = NULL;
58 return -1;
59 }
60
61 return 0;
62 }
63
64
65 static void Cio_Close( hCio h )
66 {
67 if ( h->in != NULL )
68 fclose( h->in );
69 if ( h->out != NULL )
70 fclose( h->out );
71 }
72
73
74 static int Cio_Fill( hCio h )
75 {
76
77 h->z.next_in = h->in_buf;
78 h->z.avail_in = fread( h->in_buf, 1, IN_BUFSIZE, h->in );
79 if ( h->z.avail_in <= 0 )
80 {
81 if ( ferror( h->in ) )
82 {
83
84 perror( h->in_path );
85 return -1;
86 }
87
88 return 0;
89 }
90
91 return 0;
92 }
93
94
95 static int Cio_Flush( hCio h )
96 {
97
98 if ( fwrite( h->out_buf, OUT_BUFSIZE - h->z.avail_out, 1, h->out ) != 1 )
99 {
100
101 perror( h->out_path );
102 return -1;
103 }
104 h->z.next_out = h->out_buf;
105 h->z.avail_out = OUT_BUFSIZE;
106
107 return 0;
108 }
109
110
111 static int Cio_Start( hCio h )
112 {
113 int ret;
114
115
116 h->z.zalloc = Z_NULL;
117 h->z.zfree = Z_NULL;
118 h->z.opaque = Z_NULL;
119
120
121 if ( ( ret = deflateInit( &h->z, Z_DEFAULT_COMPRESSION ) ) != Z_OK )
122 {
123 Cio_ZError( h, NULL );
124 return -1;
125 }
126
127
128 h->z.next_in = h->in_buf;
129 h->z.avail_in = 0;
130 h->z.next_out = h->out_buf;
131 h->z.avail_out = OUT_BUFSIZE;
132
133 return 0;
134 }
135
136
137 static int Cio_End( hCio h )
138 {
139 int ret;
140
141
142 if ( ( ret = deflateEnd( &h->z ) ) != Z_OK )
143 {
144 Cio_ZError( h, NULL );
145 return -1;
146 }
147
148 return 0;
149 }
150
151
152 static int Cio_Loop( hCio h )
153 {
154 int ret, flush = Z_NO_FLUSH;
155
156 while ( ( ret = deflate( &h->z, flush ) ) != Z_STREAM_END )
157 {
158 switch ( ret )
159 {
160 case Z_OK:
161 case Z_BUF_ERROR:
162
163 if ( !h->z.avail_in )
164 {
165 if ( ( ret = Cio_Fill( h ) ) )
166 return -1;
167
168
169 if ( !h->z.avail_in )
170 flush = Z_FINISH;
171 }
172
173 if ( !h->z.avail_out )
174 {
175 if ( ( ret = Cio_Flush( h ) ) )
176 return -1;
177 }
178 break;
179 case Z_STREAM_ERROR:
180
181 Cio_ZError( h, NULL );
182 return -1;
183 }
184 }
185
186
187 return Cio_Flush( h );
188 }
189
190
191 static int Cio_Compress( hCio h )
192 {
193 int ret;
194
195
196 if ( ( ret = Cio_Start( h ) ) )
197 return ret;
198
199
200 ret = Cio_Loop( h );
201
202
203 if ( !ret )
204 Cio_End( h );
205 else
206 ret = Cio_End( h );
207
208 return ret;
209 }
210
211
212 static int Compress( const char *in_path, const char *out_path )
213 {
214 int ret;
215 Cio io;
216
217
218 if ( ( ret = Cio_Open( &io, in_path, out_path ) ) )
219 return ret;
220
221
222 ret = Cio_Compress( &io );
223
224
225 Cio_Close( &io );
226
227 return ret;
228 }
229
230 int main( int argc, char *argv[] )
231 {
232 if ( argc != 3 )
233 {
234 fprintf( stderr, "Usage: %s Input Output\n", argv[0] );
235 return -1;
236 }
237
238 return Compress( argv[1], argv[2] );
239 }