forked from jverkoey/nimbus
/
_a_s_i_data_compressor_8m_source.html
315 lines (297 loc) · 21.2 KB
/
_a_s_i_data_compressor_8m_source.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>Nimbus: /Users/featherless/workbench/ios/nimbus/src/ASIHTTPRequest/src/ASIDataCompressor.m Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="stylesheet.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-24278774-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="page">
<div style="position:relative">
<div id="top"><!-- do not remove this div! -->
<div id="titlearea">
<a style="float: right;margin-right:20px;margin-top:20px" href='http://www.pledgie.com/campaigns/15519'><img alt='Click here to support Nimbus development and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/15519.png?skin_name=chrome' border='0' /></a>
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">Nimbus
 <span id="projectnumber">0.6.0 - <a href="http://github.com/jverkoey/nimbus">Nimbus is proudly hosted on Github</a></span>
</div>
<div id="projectbrief">An iOS framework whose growth is bounded by O(documentation).</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Generated by Doxygen 1.7.4-20110629 -->
</div>
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
initNavTree('_a_s_i_data_compressor_8m.html','');
</script>
<div id="doc-content">
<div class="header">
<div class="headertitle">
<div class="title">/Users/featherless/workbench/ios/nimbus/src/ASIHTTPRequest/src/ASIDataCompressor.m</div> </div>
</div>
<div class="contents">
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">//</span>
<a name="l00002"></a>00002 <span class="comment">// ASIDataCompressor.m</span>
<a name="l00003"></a>00003 <span class="comment">// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest</span>
<a name="l00004"></a>00004 <span class="comment">//</span>
<a name="l00005"></a>00005 <span class="comment">// Created by Ben Copsey on 17/08/2010.</span>
<a name="l00006"></a>00006 <span class="comment">// Copyright 2010 All-Seeing Interactive. All rights reserved.</span>
<a name="l00007"></a>00007 <span class="comment">//</span>
<a name="l00008"></a>00008
<a name="l00009"></a>00009 <span class="preprocessor">#import "ASIDataCompressor.h"</span>
<a name="l00010"></a>00010 <span class="preprocessor">#import "ASIHTTPRequest.h"</span>
<a name="l00011"></a>00011
<a name="l00012"></a>00012 <span class="preprocessor">#define DATA_CHUNK_SIZE 262144 // Deal with gzipped data in 256KB chunks</span>
<a name="l00013"></a>00013 <span class="preprocessor"></span><span class="preprocessor">#define COMPRESSION_AMOUNT Z_DEFAULT_COMPRESSION</span>
<a name="l00014"></a>00014 <span class="preprocessor"></span>
<a name="l00015"></a>00015 <span class="keyword">@interface </span>ASIDataCompressor ()
<a name="l00016"></a>00016 + (NSError *)deflateErrorWithCode:(<span class="keywordtype">int</span>)code;
<a name="l00017"></a>00017 <span class="keyword">@end</span>
<a name="l00018"></a>00018
<a name="l00019"></a>00019 <span class="keyword">@implementation </span>ASIDataCompressor
<a name="l00020"></a>00020
<a name="l00021"></a>00021 + (id)compressor
<a name="l00022"></a>00022 {
<a name="l00023"></a>00023 ASIDataCompressor *compressor = [[[<span class="keyword">self</span> alloc] init] autorelease];
<a name="l00024"></a>00024 [compressor setupStream];
<a name="l00025"></a>00025 <span class="keywordflow">return</span> compressor;
<a name="l00026"></a>00026 }
<a name="l00027"></a>00027
<a name="l00028"></a>00028 - (void)dealloc
<a name="l00029"></a>00029 {
<a name="l00030"></a>00030 <span class="keywordflow">if</span> (streamReady) {
<a name="l00031"></a>00031 [<span class="keyword">self</span> closeStream];
<a name="l00032"></a>00032 }
<a name="l00033"></a>00033 [<span class="keyword">super</span> dealloc];
<a name="l00034"></a>00034 }
<a name="l00035"></a>00035
<a name="l00036"></a>00036 - (NSError *)setupStream
<a name="l00037"></a>00037 {
<a name="l00038"></a>00038 <span class="keywordflow">if</span> (streamReady) {
<a name="l00039"></a>00039 <span class="keywordflow">return</span> nil;
<a name="l00040"></a>00040 }
<a name="l00041"></a>00041 <span class="comment">// Setup the inflate stream</span>
<a name="l00042"></a>00042 zStream.zalloc = Z_NULL;
<a name="l00043"></a>00043 zStream.zfree = Z_NULL;
<a name="l00044"></a>00044 zStream.opaque = Z_NULL;
<a name="l00045"></a>00045 zStream.avail_in = 0;
<a name="l00046"></a>00046 zStream.next_in = 0;
<a name="l00047"></a>00047 <span class="keywordtype">int</span> status = deflateInit2(&zStream, COMPRESSION_AMOUNT, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);
<a name="l00048"></a>00048 <span class="keywordflow">if</span> (status != Z_OK) {
<a name="l00049"></a>00049 <span class="keywordflow">return</span> [[<span class="keyword">self</span> class] deflateErrorWithCode:status];
<a name="l00050"></a>00050 }
<a name="l00051"></a>00051 streamReady = YES;
<a name="l00052"></a>00052 <span class="keywordflow">return</span> nil;
<a name="l00053"></a>00053 }
<a name="l00054"></a>00054
<a name="l00055"></a>00055 - (NSError *)closeStream
<a name="l00056"></a>00056 {
<a name="l00057"></a>00057 <span class="keywordflow">if</span> (!streamReady) {
<a name="l00058"></a>00058 <span class="keywordflow">return</span> nil;
<a name="l00059"></a>00059 }
<a name="l00060"></a>00060 <span class="comment">// Close the deflate stream</span>
<a name="l00061"></a>00061 streamReady = NO;
<a name="l00062"></a>00062 <span class="keywordtype">int</span> status = deflateEnd(&zStream);
<a name="l00063"></a>00063 <span class="keywordflow">if</span> (status != Z_OK) {
<a name="l00064"></a>00064 <span class="keywordflow">return</span> [[<span class="keyword">self</span> class] deflateErrorWithCode:status];
<a name="l00065"></a>00065 }
<a name="l00066"></a>00066 <span class="keywordflow">return</span> nil;
<a name="l00067"></a>00067 }
<a name="l00068"></a>00068
<a name="l00069"></a>00069 - (<a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a> *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish
<a name="l00070"></a>00070 {
<a name="l00071"></a>00071 <span class="keywordflow">if</span> (length == 0) <span class="keywordflow">return</span> nil;
<a name="l00072"></a>00072
<a name="l00073"></a>00073 NSUInteger halfLength = length/2;
<a name="l00074"></a>00074
<a name="l00075"></a>00075 <span class="comment">// We'll take a guess that the compressed data will fit in half the size of the original (ie the max to compress at once is half DATA_CHUNK_SIZE), if not, we'll increase it below</span>
<a name="l00076"></a>00076 NSMutableData *outputData = [NSMutableData dataWithLength:length/2];
<a name="l00077"></a>00077
<a name="l00078"></a>00078 <span class="keywordtype">int</span> status;
<a name="l00079"></a>00079
<a name="l00080"></a>00080 zStream.next_in = bytes;
<a name="l00081"></a>00081 zStream.avail_in = (<span class="keywordtype">unsigned</span> int)length;
<a name="l00082"></a>00082 zStream.avail_out = 0;
<a name="l00083"></a>00083
<a name="l00084"></a>00084 NSInteger bytesProcessedAlready = zStream.total_out;
<a name="l00085"></a>00085 <span class="keywordflow">while</span> (zStream.avail_out == 0) {
<a name="l00086"></a>00086
<a name="l00087"></a>00087 <span class="keywordflow">if</span> (zStream.total_out-bytesProcessedAlready >= [outputData length]) {
<a name="l00088"></a>00088 [outputData increaseLengthBy:halfLength];
<a name="l00089"></a>00089 }
<a name="l00090"></a>00090
<a name="l00091"></a>00091 zStream.next_out = [outputData mutableBytes] + zStream.total_out-bytesProcessedAlready;
<a name="l00092"></a>00092 zStream.avail_out = (<span class="keywordtype">unsigned</span> int)([outputData length] - (zStream.total_out-bytesProcessedAlready));
<a name="l00093"></a>00093 status = deflate(&zStream, shouldFinish ? Z_FINISH : Z_NO_FLUSH);
<a name="l00094"></a>00094
<a name="l00095"></a>00095 <span class="keywordflow">if</span> (status == Z_STREAM_END) {
<a name="l00096"></a>00096 <span class="keywordflow">break</span>;
<a name="l00097"></a>00097 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (status != Z_OK) {
<a name="l00098"></a>00098 <span class="keywordflow">if</span> (err) {
<a name="l00099"></a>00099 *err = [[<span class="keyword">self</span> class] deflateErrorWithCode:status];
<a name="l00100"></a>00100 }
<a name="l00101"></a>00101 <span class="keywordflow">return</span> NO;
<a name="l00102"></a>00102 }
<a name="l00103"></a>00103 }
<a name="l00104"></a>00104
<a name="l00105"></a>00105 <span class="comment">// Set real length</span>
<a name="l00106"></a>00106 [outputData setLength: zStream.total_out-bytesProcessedAlready];
<a name="l00107"></a>00107 <span class="keywordflow">return</span> outputData;
<a name="l00108"></a>00108 }
<a name="l00109"></a>00109
<a name="l00110"></a>00110
<a name="l00111"></a>00111 + (<a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a> *)compressData:(<a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a>*)uncompressedData error:(NSError **)err
<a name="l00112"></a>00112 {
<a name="l00113"></a>00113 NSError *theError = nil;
<a name="l00114"></a>00114 <a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a> *outputData = [[ASIDataCompressor compressor] compressBytes:(Bytef *)[uncompressedData bytes] length:[uncompressedData length] error:&theError shouldFinish:YES];
<a name="l00115"></a>00115 <span class="keywordflow">if</span> (theError) {
<a name="l00116"></a>00116 <span class="keywordflow">if</span> (err) {
<a name="l00117"></a>00117 *err = theError;
<a name="l00118"></a>00118 }
<a name="l00119"></a>00119 <span class="keywordflow">return</span> nil;
<a name="l00120"></a>00120 }
<a name="l00121"></a>00121 <span class="keywordflow">return</span> outputData;
<a name="l00122"></a>00122 }
<a name="l00123"></a>00123
<a name="l00124"></a>00124
<a name="l00125"></a>00125
<a name="l00126"></a>00126 + (BOOL)compressDataFromFile:(<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> *)sourcePath toFile:(<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> *)destinationPath error:(NSError **)err
<a name="l00127"></a>00127 {
<a name="l00128"></a>00128 NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
<a name="l00129"></a>00129
<a name="l00130"></a>00130 <span class="comment">// Create an empty file at the destination path</span>
<a name="l00131"></a>00131 <span class="keywordflow">if</span> (![fileManager createFileAtPath:destinationPath contents:[<a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a> data] attributes:nil]) {
<a name="l00132"></a>00132 <span class="keywordflow">if</span> (err) {
<a name="l00133"></a>00133 *err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> stringWithFormat:@"Compression of %@ failed because we were to create a file at %@",sourcePath,destinationPath],NSLocalizedDescriptionKey,nil]];
<a name="l00134"></a>00134 }
<a name="l00135"></a>00135 <span class="keywordflow">return</span> NO;
<a name="l00136"></a>00136 }
<a name="l00137"></a>00137
<a name="l00138"></a>00138 <span class="comment">// Ensure the source file exists</span>
<a name="l00139"></a>00139 <span class="keywordflow">if</span> (![fileManager fileExistsAtPath:sourcePath]) {
<a name="l00140"></a>00140 <span class="keywordflow">if</span> (err) {
<a name="l00141"></a>00141 *err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> stringWithFormat:@"Compression of %@ failed the file does not exist",sourcePath],NSLocalizedDescriptionKey,nil]];
<a name="l00142"></a>00142 }
<a name="l00143"></a>00143 <span class="keywordflow">return</span> NO;
<a name="l00144"></a>00144 }
<a name="l00145"></a>00145
<a name="l00146"></a>00146 UInt8 inputData[DATA_CHUNK_SIZE];
<a name="l00147"></a>00147 <a class="code" href="class_n_s_data.html" title="For hashing raw data.">NSData</a> *outputData;
<a name="l00148"></a>00148 NSInteger readLength;
<a name="l00149"></a>00149 NSError *theError = nil;
<a name="l00150"></a>00150
<a name="l00151"></a>00151 ASIDataCompressor *compressor = [ASIDataCompressor compressor];
<a name="l00152"></a>00152
<a name="l00153"></a>00153 NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:sourcePath];
<a name="l00154"></a>00154 [inputStream open];
<a name="l00155"></a>00155 NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:destinationPath append:NO];
<a name="l00156"></a>00156 [outputStream open];
<a name="l00157"></a>00157
<a name="l00158"></a>00158 <span class="keywordflow">while</span> ([compressor streamReady]) {
<a name="l00159"></a>00159
<a name="l00160"></a>00160 <span class="comment">// Read some data from the file</span>
<a name="l00161"></a>00161 readLength = [inputStream read:inputData maxLength:DATA_CHUNK_SIZE];
<a name="l00162"></a>00162
<a name="l00163"></a>00163 <span class="comment">// Make sure nothing went wrong</span>
<a name="l00164"></a>00164 <span class="keywordflow">if</span> ([inputStream streamStatus] == NSStreamEventErrorOccurred) {
<a name="l00165"></a>00165 <span class="keywordflow">if</span> (err) {
<a name="l00166"></a>00166 *err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> stringWithFormat:@"Compression of %@ failed because we were unable to read from the source data file",sourcePath],NSLocalizedDescriptionKey,[inputStream streamError],NSUnderlyingErrorKey,nil]];
<a name="l00167"></a>00167 }
<a name="l00168"></a>00168 [compressor closeStream];
<a name="l00169"></a>00169 <span class="keywordflow">return</span> NO;
<a name="l00170"></a>00170 }
<a name="l00171"></a>00171 <span class="comment">// Have we reached the end of the input data?</span>
<a name="l00172"></a>00172 <span class="keywordflow">if</span> (!readLength) {
<a name="l00173"></a>00173 <span class="keywordflow">break</span>;
<a name="l00174"></a>00174 }
<a name="l00175"></a>00175
<a name="l00176"></a>00176 <span class="comment">// Attempt to deflate the chunk of data</span>
<a name="l00177"></a>00177 outputData = [compressor compressBytes:inputData length:readLength error:&theError shouldFinish:readLength < DATA_CHUNK_SIZE ];
<a name="l00178"></a>00178 <span class="keywordflow">if</span> (theError) {
<a name="l00179"></a>00179 <span class="keywordflow">if</span> (err) {
<a name="l00180"></a>00180 *err = theError;
<a name="l00181"></a>00181 }
<a name="l00182"></a>00182 [compressor closeStream];
<a name="l00183"></a>00183 <span class="keywordflow">return</span> NO;
<a name="l00184"></a>00184 }
<a name="l00185"></a>00185
<a name="l00186"></a>00186 <span class="comment">// Write the deflated data out to the destination file</span>
<a name="l00187"></a>00187 [outputStream write:[outputData bytes] maxLength:[outputData length]];
<a name="l00188"></a>00188
<a name="l00189"></a>00189 <span class="comment">// Make sure nothing went wrong</span>
<a name="l00190"></a>00190 <span class="keywordflow">if</span> ([inputStream streamStatus] == NSStreamEventErrorOccurred) {
<a name="l00191"></a>00191 <span class="keywordflow">if</span> (err) {
<a name="l00192"></a>00192 *err = [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> stringWithFormat:@"Compression of %@ failed because we were unable to write to the destination data file at &@",sourcePath,destinationPath],NSLocalizedDescriptionKey,[outputStream streamError],NSUnderlyingErrorKey,nil]];
<a name="l00193"></a>00193 }
<a name="l00194"></a>00194 [compressor closeStream];
<a name="l00195"></a>00195 <span class="keywordflow">return</span> NO;
<a name="l00196"></a>00196 }
<a name="l00197"></a>00197
<a name="l00198"></a>00198 }
<a name="l00199"></a>00199 [inputStream close];
<a name="l00200"></a>00200 [outputStream close];
<a name="l00201"></a>00201
<a name="l00202"></a>00202 NSError *error = [compressor closeStream];
<a name="l00203"></a>00203 <span class="keywordflow">if</span> (error) {
<a name="l00204"></a>00204 <span class="keywordflow">if</span> (err) {
<a name="l00205"></a>00205 *err = error;
<a name="l00206"></a>00206 }
<a name="l00207"></a>00207 <span class="keywordflow">return</span> NO;
<a name="l00208"></a>00208 }
<a name="l00209"></a>00209
<a name="l00210"></a>00210 <span class="keywordflow">return</span> YES;
<a name="l00211"></a>00211 }
<a name="l00212"></a>00212
<a name="l00213"></a>00213 + (NSError *)deflateErrorWithCode:(<span class="keywordtype">int</span>)code
<a name="l00214"></a>00214 {
<a name="l00215"></a>00215 <span class="keywordflow">return</span> [NSError errorWithDomain:NetworkRequestErrorDomain code:ASICompressionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[<a class="code" href="class_n_s_string.html" title="For manipulating NSStrings.">NSString</a> stringWithFormat:@"Compression of data failed with code %hi",code],NSLocalizedDescriptionKey,nil]];
<a name="l00216"></a>00216 }
<a name="l00217"></a>00217
<a name="l00218"></a>00218 <span class="keyword">@synthesize</span> streamReady;
<a name="l00219"></a>00219 <span class="keyword">@end</span>
</pre></div></div>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><b>ASIDataCompressor.m</b> </li>
</div><!-- .fixedwidth -->
<span class="footer">Generated for Nimbus by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.7.4-20110629 </span>
</ul>
</div>
</div> <!-- page -->
</body>
</html>