diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..56fffb6 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,19 @@ +name: test + +on: + pull_request: + +permissions: + contents: read + +jobs: + unit: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '20' + - run: npm install + - run: npm test \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a89908b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +output +node_modules \ No newline at end of file diff --git a/abaplint.jsonc b/abaplint.jsonc new file mode 100644 index 0000000..7f2831e --- /dev/null +++ b/abaplint.jsonc @@ -0,0 +1,29 @@ +{ + "global": { + "files": "/src/**/*.*" + }, + "dependencies": [ + { + "url": "https://github.com/open-abap/open-abap-core", + "folder": "/deps", + "files": "/src/**/*.*" + } + ], + "syntax": { + "version": "v702", + "errorNamespace": "." + }, + "rules": { + "begin_end_names": true, + "check_ddic": true, + "check_include": true, + "check_syntax": true, + "global_class": true, + "implement_methods": true, + "method_implemented_twice": true, + "parser_error": true, + "superclass_final": true, + "unknown_types": true, + "xml_consistency": true + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e5c754d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,72 @@ +{ + "name": "crc32c", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "crc32c", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@abaplint/cli": "^2.102.42", + "@abaplint/runtime": "^2.7.97", + "@abaplint/transpiler-cli": "^2.7.97" + } + }, + "node_modules/@abaplint/cli": { + "version": "2.102.42", + "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.102.42.tgz", + "integrity": "sha512-HGhBo15ZQ0yrS2udpBdjG5m2hE7wlmC5S2ucVGs3R7x7TWvoy0bQRlPPsXXOpUB3tnumkGooUyvDthubhz46KQ==", + "dev": true, + "bin": { + "abaplint": "abaplint" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/@abaplint/runtime": { + "version": "2.7.97", + "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.97.tgz", + "integrity": "sha512-2PpEHlOC5vM+hfNpu+LT4sxqF4Yx2xOwo3NqTX564sPj/cxND18IoCK9IyD2lgBH0q8P0/TMPtZAuPFM/8Eg0w==", + "dev": true, + "dependencies": { + "temporal-polyfill": "^0.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/@abaplint/transpiler-cli": { + "version": "2.7.97", + "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.97.tgz", + "integrity": "sha512-oZaIxxvzOz5HHHXsmLjjyHgMg01no9tOQMAQPfwnDSSAb1mPQc80Ql0zLJkS4dm9rWAIK9HB9BVnZOClTWxshg==", + "dev": true, + "bin": { + "abap_transpile": "abap_transpile" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/temporal-polyfill": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.1.1.tgz", + "integrity": "sha512-/5e4EVRA0wBI/bEhWLirSjwUg1lELhQyTXxw9zNbVhqjKvI9BLczs+3wtsoD9sn3HN2ImAMW5XJQwAiXgWT+GA==", + "dev": true, + "dependencies": { + "temporal-spec": "~0.1.0" + } + }, + "node_modules/temporal-spec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.1.0.tgz", + "integrity": "sha512-sMNggMeS6trCgMQuudgFHhX1gtBK3e+AT1zGrMsFYG1wlqtRT5E9rcvm3I1iNlvHpJX/3DO6L4qtWAuEl/T04Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..812a726 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "crc32c", + "private": true, + "version": "1.0.0", + "description": "CRC32C (Castagnoli)", + "scripts": { + "transpile": "rm -rf output && abap_transpile", + "unit": "npm run transpile && echo RUNNING && node output/index.mjs && echo OK", + "lint": "abaplint", + "test": "npm run lint && npm run unit" + }, + "author": "Lars Hvam Petersen", + "license": "MIT", + "devDependencies": { + "@abaplint/cli": "^2.102.42", + "@abaplint/runtime": "^2.7.97", + "@abaplint/transpiler-cli": "^2.7.97" + } +} diff --git a/src/zcl_crc32c.clas.abap b/src/zcl_crc32c.clas.abap new file mode 100644 index 0000000..e07db1c --- /dev/null +++ b/src/zcl_crc32c.clas.abap @@ -0,0 +1,65 @@ +CLASS zcl_crc32c DEFINITION PUBLIC. + PUBLIC SECTION. + TYPES ty_crc TYPE x LENGTH 4. + + CLASS-METHODS run + IMPORTING + iv_xstring TYPE xstring + RETURNING + VALUE(rv_crc) TYPE ty_crc. + PRIVATE SECTION. + CLASS-DATA crc32_map TYPE xstring. +ENDCLASS. + +CLASS zcl_crc32c IMPLEMENTATION. + METHOD run. +* https://en.wikipedia.org/wiki/Cyclic_redundancy_check + + CONSTANTS: magic_nr TYPE x LENGTH 4 VALUE '82F63B78', + mffffffff TYPE x LENGTH 4 VALUE 'FFFFFFFF', + m7fffffff TYPE x LENGTH 4 VALUE '7FFFFFFF', + m00ffffff TYPE x LENGTH 4 VALUE '00FFFFFF', + m000000ff TYPE x LENGTH 4 VALUE '000000FF', + m000000 TYPE x LENGTH 3 VALUE '000000'. + + DATA: cindex TYPE x LENGTH 4, + low_bit TYPE x LENGTH 4, + len TYPE i, + nindex TYPE i, + crc TYPE x LENGTH 4 VALUE mffffffff, + x4 TYPE x LENGTH 4, + idx TYPE x LENGTH 4. + + IF xstrlen( crc32_map ) = 0. + DO 256 TIMES. + cindex = sy-index - 1. + DO 8 TIMES. + low_bit = '00000001'. + low_bit = cindex BIT-AND low_bit. " c & 1 + cindex = cindex DIV 2. + cindex = cindex BIT-AND m7fffffff. " c >> 1 (top is zero, but in ABAP signed!) + IF low_bit IS NOT INITIAL. + cindex = cindex BIT-XOR magic_nr. + ENDIF. + ENDDO. + CONCATENATE crc32_map cindex INTO crc32_map IN BYTE MODE. + ENDDO. + ENDIF. + + len = xstrlen( iv_xstring ). + DO len TIMES. + nindex = sy-index - 1. + CONCATENATE m000000 iv_xstring+nindex(1) INTO idx IN BYTE MODE. + idx = ( crc BIT-XOR idx ) BIT-AND m000000ff. + idx = idx * 4. + x4 = crc32_map+idx(4). + crc = crc DIV 256. + crc = crc BIT-AND m00ffffff. " c >> 8 + crc = x4 BIT-XOR crc. + ENDDO. + crc = crc BIT-XOR mffffffff. + + rv_crc = crc. + + ENDMETHOD. +ENDCLASS. \ No newline at end of file diff --git a/src/zcl_crc32c.clas.testclasses.abap b/src/zcl_crc32c.clas.testclasses.abap new file mode 100644 index 0000000..603433a --- /dev/null +++ b/src/zcl_crc32c.clas.testclasses.abap @@ -0,0 +1,27 @@ +CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL. + PRIVATE SECTION. + METHODS test FOR TESTING RAISING cx_static_check. +ENDCLASS. + + +CLASS ltcl_test IMPLEMENTATION. + + METHOD test. + + DATA lv_xstr TYPE xstring. + DATA lv_crc TYPE zcl_crc32c=>ty_crc. + +* https://crccalc.com/?crc=1122334455667788AABBCCDDEEFF&method=crc32&datatype=hex&outtype=0 + lv_xstr = '1122334455667788AABBCCDDEEFF'. + + lv_crc = zcl_crc32c=>run( lv_xstr ). + + cl_abap_unit_assert=>assert_not_initial( lv_crc ). + + cl_abap_unit_assert=>assert_equals( + exp = 'F44CB56B' + act = lv_crc ). + + ENDMETHOD. + +ENDCLASS. diff --git a/src/zcl_crc32c.clas.xml b/src/zcl_crc32c.clas.xml new file mode 100644 index 0000000..4ac4704 --- /dev/null +++ b/src/zcl_crc32c.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_CRC32C + E + ZCL_CRC32C + 1 + X + X + X + + + + \ No newline at end of file