@@ -237,3 +237,88 @@ const uint8 *FindAddrInMemblk(MemBlk data, uint32 addr) {
237237 return 0 ;
238238 return data .ptr + offset ;
239239}
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