abapGit/src/zlib/zcl_abapgit_zlib_stream.clas.abap
sandraros 8e2e2f13fc shortdump ZCL_ABAPGIT_ZLIB->Decompress #2483 (#2600)
* shortdump ZCL_ABAPGIT_ZLIB->Decompress #2483

Short dump ASSERTION_FAILED while pulling from a Git repository.

It's because of block type '00' (variable `lv_btype`) not handled at all.

00 is "non-compressed blocks", see https://www.ietf.org/rfc/rfc1951.txt section 3.2.4

The issue used to happen with Azure DevOps website, for "tree" objects (100644...) but not all tree objects.

Correction : algorithm added to handle non-compressed blocks. Test method added to complete the current test for blocks with fixed Huffman codes (01). Also one test method added for testing blocks with dynamic Huffman codes (10), test data taken from ZAZLIB.

* Lint code alignment issue
2019-03-30 03:19:55 -07:00

101 lines
2.2 KiB
ABAP

CLASS zcl_abapgit_zlib_stream DEFINITION
PUBLIC
CREATE PUBLIC .
PUBLIC SECTION.
METHODS constructor
IMPORTING
!iv_data TYPE xstring .
METHODS take_bits
IMPORTING
!iv_length TYPE i
RETURNING
VALUE(rv_bits) TYPE string .
METHODS take_int
IMPORTING
!iv_length TYPE i
RETURNING
VALUE(rv_int) TYPE i .
METHODS remaining
RETURNING
VALUE(rv_length) TYPE i .
"! Take bytes, there's an implicit realignment to start at the beginning of a byte
"! i.e. if next bit of current byte is not the first bit, then this byte is skipped
"! and the bytes are taken from the next one.
"! @parameter iv_length | <p class="shorttext synchronized" lang="en">Number of BYTES to read (not bits)</p>
"! @parameter rv_bytes | <p class="shorttext synchronized" lang="en">Bytes taken</p>
METHODS take_bytes
IMPORTING
iv_length TYPE i
RETURNING
VALUE(rv_bytes) TYPE xstring.
PROTECTED SECTION.
PRIVATE SECTION.
DATA: mv_compressed TYPE xstring,
mv_bits TYPE string.
ENDCLASS.
CLASS zcl_abapgit_zlib_stream IMPLEMENTATION.
METHOD constructor.
mv_compressed = iv_data.
ENDMETHOD.
METHOD remaining.
rv_length = xstrlen( mv_compressed ) + 1.
ENDMETHOD.
METHOD take_bits.
DATA: lv_left TYPE i,
lv_index TYPE i,
lv_x TYPE x LENGTH 1.
WHILE strlen( rv_bits ) < iv_length.
IF mv_bits IS INITIAL.
lv_x = mv_compressed(1).
mv_bits = zcl_abapgit_zlib_convert=>hex_to_bits( lv_x ).
mv_compressed = mv_compressed+1.
ENDIF.
lv_left = iv_length - strlen( rv_bits ).
IF lv_left >= strlen( mv_bits ).
CONCATENATE mv_bits rv_bits INTO rv_bits.
CLEAR mv_bits.
ELSE.
lv_index = strlen( mv_bits ) - lv_left.
CONCATENATE mv_bits+lv_index(lv_left) rv_bits INTO rv_bits.
mv_bits = mv_bits(lv_index).
ENDIF.
ENDWHILE.
ENDMETHOD.
METHOD take_bytes.
rv_bytes = mv_compressed(iv_length).
mv_compressed = mv_compressed+iv_length.
ENDMETHOD.
METHOD take_int.
rv_int = zcl_abapgit_zlib_convert=>bits_to_int( take_bits( iv_length ) ).
ENDMETHOD.
ENDCLASS.