@@ -237,3 +237,88 @@ const uint8 *FindAddrInMemblk(MemBlk data, uint32 addr) {
237
237
return 0 ;
238
238
return data .ptr + offset ;
239
239
}
240
+
241
+ static uint64 BpsDecodeInt (const uint8 * * src ) {
242
+ uint64 data = 0 , shift = 1 ;
243
+ while (true) {
244
+ uint8 x = * (* src )++ ;
245
+ data += (x & 0x7f ) * shift ;
246
+ if (x & 0x80 ) break ;
247
+ shift <<= 7 ;
248
+ data += shift ;
249
+ }
250
+ return data ;
251
+ }
252
+
253
+ #define CRC32_POLYNOMIAL 0xEDB88320
254
+
255
+ static uint32 crc32 (const void * data , size_t length ) {
256
+ uint32 crc = 0xFFFFFFFF ;
257
+ const uint8 * byteData = (const uint8 * )data ;
258
+ for (size_t i = 0 ; i < length ; i ++ ) {
259
+ crc ^= byteData [i ];
260
+ for (int j = 0 ; j < 8 ; j ++ )
261
+ crc = (crc >> 1 ) ^ ((crc & 1 ) * CRC32_POLYNOMIAL );
262
+ }
263
+ return crc ^ 0xFFFFFFFF ;
264
+ }
265
+
266
+
267
+ uint8 * ApplyBps (const uint8 * src , size_t src_size_in ,
268
+ const uint8 * bps , size_t bps_size , size_t * length_out ) {
269
+ const uint8 * bps_end = bps + bps_size - 12 ;
270
+
271
+ if (memcmp (bps , "BPS1" , 4 ))
272
+ return NULL ;
273
+ if (crc32 (src , src_size_in ) != * (uint32 * )(bps_end ))
274
+ return NULL ;
275
+ if (crc32 (bps , bps_size - 4 ) != * (uint32 * )(bps_end + 8 ))
276
+ return NULL ;
277
+
278
+ bps += 4 ;
279
+ uint32 src_size = BpsDecodeInt (& bps );
280
+ uint32 dst_size = BpsDecodeInt (& bps );
281
+ uint32 meta_size = BpsDecodeInt (& bps );
282
+ uint32 outputOffset = 0 ;
283
+ uint32 sourceRelativeOffset = 0 ;
284
+ uint32 targetRelativeOffset = 0 ;
285
+ if (src_size != src_size_in )
286
+ return NULL ;
287
+ * length_out = dst_size ;
288
+ uint8 * dst = malloc (dst_size );
289
+ if (!dst )
290
+ return NULL ;
291
+ while (bps < bps_end ) {
292
+ uint32 cmd = BpsDecodeInt (& bps );
293
+ uint32 length = (cmd >> 2 ) + 1 ;
294
+ switch (cmd & 3 ) {
295
+ case 0 :
296
+ while (length -- ) {
297
+ dst [outputOffset ] = src [outputOffset ];
298
+ outputOffset ++ ;
299
+ }
300
+ break ;
301
+ case 1 :
302
+ while (length -- )
303
+ dst [outputOffset ++ ] = * bps ++ ;
304
+ break ;
305
+ case 2 :
306
+ cmd = BpsDecodeInt (& bps );
307
+ sourceRelativeOffset += (cmd & 1 ? -1 : +1 ) * (cmd >> 1 );
308
+ while (length -- )
309
+ dst [outputOffset ++ ] = src [sourceRelativeOffset ++ ];
310
+ break ;
311
+ default :
312
+ cmd = BpsDecodeInt (& bps );
313
+ targetRelativeOffset += (cmd & 1 ? -1 : +1 ) * (cmd >> 1 );
314
+ while (length -- )
315
+ dst [outputOffset ++ ] = dst [targetRelativeOffset ++ ];
316
+ break ;
317
+ }
318
+ }
319
+ if (dst_size != outputOffset )
320
+ return NULL ;
321
+ if (crc32 (dst , dst_size ) != * (uint32 * )(bps_end + 4 ))
322
+ return NULL ;
323
+ return dst ;
324
+ }
0 commit comments