abapGit/src/utils/zcl_abapgit_hash.clas.abap
2018-08-01 18:55:31 +02:00

130 lines
2.9 KiB
ABAP

CLASS zcl_abapgit_hash DEFINITION
PUBLIC
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-METHODS adler32
IMPORTING
!iv_xstring TYPE xstring
RETURNING
VALUE(rv_checksum) TYPE zif_abapgit_definitions=>ty_adler32 .
CLASS-METHODS sha1
IMPORTING
!iv_type TYPE zif_abapgit_definitions=>ty_type
!iv_data TYPE xstring
RETURNING
VALUE(rv_sha1) TYPE zif_abapgit_definitions=>ty_sha1
RAISING
zcx_abapgit_exception .
CLASS-METHODS sha1_raw
IMPORTING
!iv_data TYPE xstring
RETURNING
VALUE(rv_sha1) TYPE zif_abapgit_definitions=>ty_sha1
RAISING
zcx_abapgit_exception .
ENDCLASS.
CLASS ZCL_ABAPGIT_HASH IMPLEMENTATION.
METHOD adler32.
CONSTANTS: lc_adler TYPE i VALUE 65521,
lc_max_b TYPE i VALUE 1800000000.
DATA: lv_index TYPE i,
lv_a TYPE i VALUE 1,
lv_b TYPE i VALUE 0,
lv_x TYPE x LENGTH 2,
lv_ca TYPE c LENGTH 4,
lv_cb TYPE c LENGTH 4,
lv_char8 TYPE c LENGTH 8.
DO xstrlen( iv_xstring ) TIMES.
lv_index = sy-index - 1.
lv_a = lv_a + iv_xstring+lv_index(1).
lv_b = lv_b + lv_a.
* delay the MOD operation until the integer might overflow
* articles describe 5552 additions are allowed, but this assumes unsigned integers
* instead of allowing a fixed number of additions before running MOD, then
* just compare value of lv_b, this is 1 operation less than comparing and adding
IF lv_b > lc_max_b.
lv_a = lv_a MOD lc_adler.
lv_b = lv_b MOD lc_adler.
ENDIF.
ENDDO.
lv_a = lv_a MOD lc_adler.
lv_b = lv_b MOD lc_adler.
lv_x = lv_a.
lv_ca = lv_x.
lv_x = lv_b.
lv_cb = lv_x.
CONCATENATE lv_cb lv_ca INTO lv_char8.
rv_checksum = lv_char8.
ENDMETHOD.
METHOD sha1.
DATA: lv_len TYPE i,
lv_char10 TYPE c LENGTH 10,
lv_string TYPE string,
lv_xstring TYPE xstring.
lv_len = xstrlen( iv_data ).
lv_char10 = lv_len.
CONDENSE lv_char10.
CONCATENATE iv_type lv_char10 INTO lv_string SEPARATED BY space.
lv_xstring = zcl_abapgit_convert=>string_to_xstring_utf8( lv_string ).
lv_string = lv_xstring.
CONCATENATE lv_string '00' INTO lv_string.
lv_xstring = lv_string.
CONCATENATE lv_xstring iv_data INTO lv_xstring IN BYTE MODE.
rv_sha1 = sha1_raw( lv_xstring ).
ENDMETHOD.
METHOD sha1_raw.
DATA: lv_hash TYPE hash160.
CALL FUNCTION 'CALCULATE_HASH_FOR_RAW'
EXPORTING
data = iv_data
IMPORTING
hash = lv_hash
EXCEPTIONS
unknown_alg = 1
param_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( 'Error while calculating SHA1' ).
ENDIF.
rv_sha1 = lv_hash.
TRANSLATE rv_sha1 TO LOWER CASE.
ENDMETHOD.
ENDCLASS.