@@ -193,3 +193,88 @@ MemBlk FindIndexInMemblk(MemBlk data, size_t i) {
193
193
return (MemBlk ) { 0 , 0 };
194
194
return (MemBlk ) { data .ptr + left_off , right_off - left_off };
195
195
}
196
+
197
+
198
+ static uint64 BpsDecodeInt (const uint8 * * src ) {
199
+ uint64 data = 0 , shift = 1 ;
200
+ while (true) {
201
+ uint8 x = * (* src )++ ;
202
+ data += (x & 0x7f ) * shift ;
203
+ if (x & 0x80 ) break ;
204
+ shift <<= 7 ;
205
+ data += shift ;
206
+ }
207
+ return data ;
208
+ }
209
+
210
+ #define CRC32_POLYNOMIAL 0xEDB88320
211
+
212
+ static uint32 crc32 (const void * data , size_t length ) {
213
+ uint32 crc = 0xFFFFFFFF ;
214
+ const uint8 * byteData = (const uint8 * )data ;
215
+ for (size_t i = 0 ; i < length ; i ++ ) {
216
+ crc ^= byteData [i ];
217
+ for (int j = 0 ; j < 8 ; j ++ )
218
+ crc = (crc >> 1 ) ^ ((crc & 1 ) * CRC32_POLYNOMIAL );
219
+ }
220
+ return crc ^ 0xFFFFFFFF ;
221
+ }
222
+
223
+ uint8 * ApplyBps (const uint8 * src , size_t src_size_in ,
224
+ const uint8 * bps , size_t bps_size , size_t * length_out ) {
225
+ const uint8 * bps_end = bps + bps_size - 12 ;
226
+
227
+ if (memcmp (bps , "BPS1" , 4 ))
228
+ return NULL ;
229
+ if (crc32 (src , src_size_in ) != * (uint32 * )(bps_end ))
230
+ return NULL ;
231
+ if (crc32 (bps , bps_size - 4 ) != * (uint32 * )(bps_end + 8 ))
232
+ return NULL ;
233
+
234
+ bps += 4 ;
235
+ uint32 src_size = BpsDecodeInt (& bps );
236
+ uint32 dst_size = BpsDecodeInt (& bps );
237
+ uint32 meta_size = BpsDecodeInt (& bps );
238
+ uint32 outputOffset = 0 ;
239
+ uint32 sourceRelativeOffset = 0 ;
240
+ uint32 targetRelativeOffset = 0 ;
241
+ if (src_size != src_size_in )
242
+ return NULL ;
243
+ * length_out = dst_size ;
244
+ uint8 * dst = malloc (dst_size );
245
+ if (!dst )
246
+ return NULL ;
247
+ while (bps < bps_end ) {
248
+ uint32 cmd = BpsDecodeInt (& bps );
249
+ uint32 length = (cmd >> 2 ) + 1 ;
250
+ switch (cmd & 3 ) {
251
+ case 0 :
252
+ while (length -- ) {
253
+ dst [outputOffset ] = src [outputOffset ];
254
+ outputOffset ++ ;
255
+ }
256
+ break ;
257
+ case 1 :
258
+ while (length -- )
259
+ dst [outputOffset ++ ] = * bps ++ ;
260
+ break ;
261
+ case 2 :
262
+ cmd = BpsDecodeInt (& bps );
263
+ sourceRelativeOffset += (cmd & 1 ? -1 : +1 ) * (cmd >> 1 );
264
+ while (length -- )
265
+ dst [outputOffset ++ ] = src [sourceRelativeOffset ++ ];
266
+ break ;
267
+ default :
268
+ cmd = BpsDecodeInt (& bps );
269
+ targetRelativeOffset += (cmd & 1 ? -1 : +1 ) * (cmd >> 1 );
270
+ while (length -- )
271
+ dst [outputOffset ++ ] = dst [targetRelativeOffset ++ ];
272
+ break ;
273
+ }
274
+ }
275
+ if (dst_size != outputOffset )
276
+ return NULL ;
277
+ if (crc32 (dst , dst_size ) != * (uint32 * )(bps_end + 4 ))
278
+ return NULL ;
279
+ return dst ;
280
+ }
0 commit comments