From 34f8f872cf986749d6f433cb205e10506c1188f7 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 24 Nov 2023 11:34:47 +0100 Subject: [PATCH 01/60] Version updated --- .version | 2 +- make/r3-view.rc | 4 ++-- make/r3.rc | 8 ++++---- make/rebol3.nest | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.version b/.version index 4bcbd94b52..d0adf2c9ce 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -3.15.0 \ No newline at end of file +3.15.1 \ No newline at end of file diff --git a/make/r3-view.rc b/make/r3-view.rc index f72b0c35e4..61f0c59368 100644 --- a/make/r3-view.rc +++ b/make/r3-view.rc @@ -1,8 +1,8 @@ 101 ICON "icon/r3.ico" 1 VERSIONINFO -FILEVERSION 3,15,0,0 -PRODUCTVERSION 3,15,0,0 +FILEVERSION 3,15,1,0 +PRODUCTVERSION 3,15,1,0 BEGIN BLOCK "StringFileInfo" BEGIN diff --git a/make/r3.rc b/make/r3.rc index 48f9c180b4..aa6f7b4403 100644 --- a/make/r3.rc +++ b/make/r3.rc @@ -1,20 +1,20 @@ 101 ICON "icon/r3.ico" 1 VERSIONINFO -FILEVERSION 3,14,1,0 -PRODUCTVERSION 3,14,1,0 +FILEVERSION 3,15,1,0 +PRODUCTVERSION 3,15,1,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "Rebol Console" - VALUE "FileVersion", "3.14" + VALUE "FileVersion", "3.15" VALUE "InternalName", "Rebol 3 (Oldes branch)" VALUE "LegalCopyright", "2012 REBOL Technologies" VALUE "OriginalFilename", "Rebol.exe" VALUE "ProductName", "Rebol" - VALUE "ProductVersion", "3.14" + VALUE "ProductVersion", "3.15" END END BLOCK "VarFileInfo" diff --git a/make/rebol3.nest b/make/rebol3.nest index 8ca932f6f8..c72775a00f 100644 --- a/make/rebol3.nest +++ b/make/rebol3.nest @@ -18,7 +18,7 @@ temp: %make/tmp/ stack-size: 4194304 ;= 4MB (4 * 1024 * 1024) optimize: 2 -version: 3.15.0 +version: 3.15.1 #if Linux? [ defines: TO_LINUX ] #if macOS? [ defines: TO_MACOS ] From abc6ecc0b2f6a52a5fdc8724d9c5483f7d9a0757 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 24 Nov 2023 11:35:47 +0100 Subject: [PATCH 02/60] CHANGE: using system error codes when opening a MIDI device on Windows --- src/os/win32/dev-midi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/os/win32/dev-midi.c b/src/os/win32/dev-midi.c index dfc50f8c6b..c5b46173a8 100644 --- a/src/os/win32/dev-midi.c +++ b/src/os/win32/dev-midi.c @@ -332,14 +332,14 @@ static void PrintMidiDevices() if(!device_in && !device_out) { LOG("No devices!\n"); - req->error = 1; + req->error = MMSYSERR_BADDEVICEID; return DR_ERROR; } port_num = Get_New_Midi_Port(&midi_port); if (port_num < 0) { LOG("Failed to get new empty MIDI port!\n"); - req->error = 2; + req->error = MMSYSERR_ERROR; return DR_ERROR; } @@ -354,7 +354,7 @@ static void PrintMidiDevices() || (device_out && device_out > midiOutGetNumDevs()) ) { LOG("Some of the requested MIDI device IDs are out of range!\n"); - req->error = 3; + req->error = MMSYSERR_BADDEVICEID; return DR_ERROR; } @@ -365,7 +365,7 @@ static void PrintMidiDevices() rv = midiInOpen(&midi_port->inp_device, device_in - 1, (DWORD_PTR)MidiInProc, (DWORD_PTR)port_num, CALLBACK_FUNCTION); if (rv != MMSYSERR_NOERROR) { LOG("midiInOpen() failed...rv=%d\n", rv); - req->error = 4; + req->error = rv; return DR_ERROR; } midiInStart(midi_port->inp_device); @@ -388,7 +388,7 @@ static void PrintMidiDevices() midiInClose(midi_port->inp_device); midi_port->inp_device = NULL; } - req->error = 5; + req->error = rv; return DR_ERROR; } } From 905d5f655f9b1dccbbee65726663830320aaeb84 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 24 Nov 2023 13:56:50 +0100 Subject: [PATCH 03/60] Build: accept failed signature on macos --- .github/workflows/build-all.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-all.yml b/.github/workflows/build-all.yml index 41fe239915..3af0a1a599 100644 --- a/.github/workflows/build-all.yml +++ b/.github/workflows/build-all.yml @@ -302,7 +302,8 @@ jobs: /usr/bin/codesign --force -s $MACOS_IDENTITY_ID ./build/rebol3-base-macos-arm64 -v /usr/bin/codesign --force -s $MACOS_IDENTITY_ID ./build/rebol3-core-macos-arm64 -v /usr/bin/codesign --force -s $MACOS_IDENTITY_ID ./build/rebol3-bulk-macos-arm64 -v - + continue-on-error: true + - name: Test x64 macOS versions run: | ./build/rebol3-base-macos-x64 -v From 05d2f21d5f2c8868e98018fb3aa3bb86c0699475 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 17:14:23 +0100 Subject: [PATCH 04/60] Build: Include GitHub action to test a bootstrap compilation --- .github/workflows/bootstrap.yml | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/bootstrap.yml diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml new file mode 100644 index 0000000000..77a9eb5d63 --- /dev/null +++ b/.github/workflows/bootstrap.yml @@ -0,0 +1,45 @@ +name: 'Rebol Boostrap CI' +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ bootstrap ] + paths: + - make/** + - src/** + - .github/workflows/main.yml + + pull_request: + branches: [ bootstrap ] + + # Allows you to run this workflow manually from the Actions tab + #workflow_dispatch: + +jobs: + linux: + strategy: + fail-fast: true + matrix: + os: [ubuntu-20.04] + #os: [ubuntu-20.04, ubuntu-18.04] + + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Build 64bit Rebol bootstrap using gcc + run: | + cd make/ + make -f rebol-linux-bootstrap-64bit.mk + mv ./rebol-linux-bootstrap-64bit ./rebol + + - name: Test 64bit Rebol bootstrap + run: ./make/rebol-linux-bootstrap-64bit -v + + - name: Compile real Rebol/Bulk using the Siskin Builder + run: | + git clone https://github.com/Siskin-Framework/Builder --depth 1 + cd Builder/ + ../rebol siskin.r3 rebol rebol3-bulk-linux-x64 + ./build/rebol3-bulk-linux-x64 -v + From 578759631943119f7c8be87e2e64c747e31b42dc Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 17:22:32 +0100 Subject: [PATCH 05/60] Build: allow manual bootstrap CI workflow dispatch --- .github/workflows/bootstrap.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index 77a9eb5d63..c408827648 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -6,13 +6,13 @@ on: paths: - make/** - src/** - - .github/workflows/main.yml + - .github/workflows/bootstrap.yml pull_request: branches: [ bootstrap ] # Allows you to run this workflow manually from the Actions tab - #workflow_dispatch: + workflow_dispatch: jobs: linux: From 59a27f29236fd83ea81a64cd963b681b85792bbb Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 17:42:10 +0100 Subject: [PATCH 06/60] Build: fixed GitHub action workflow for a bootstrap compilation --- .github/workflows/bootstrap.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index c408827648..30b588df62 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -31,15 +31,19 @@ jobs: run: | cd make/ make -f rebol-linux-bootstrap-64bit.mk - mv ./rebol-linux-bootstrap-64bit ./rebol + mv ./rebol-linux-bootstrap-64bit ../rebol-stage0 - name: Test 64bit Rebol bootstrap - run: ./make/rebol-linux-bootstrap-64bit -v + run: ./rebol-stage0 -v - name: Compile real Rebol/Bulk using the Siskin Builder run: | git clone https://github.com/Siskin-Framework/Builder --depth 1 cd Builder/ - ../rebol siskin.r3 rebol rebol3-bulk-linux-x64 - ./build/rebol3-bulk-linux-x64 -v + ../rebol-stage0 siskin.r3 rebol rebol3-bulk-linux-x64 + + - name: Test 64bit Rebol/Bulk + run: | + mv Builder/tree/rebol/Rebol/build/rebol3-bulk-linux-x64 ./rebol3 + ./rebol3 -v From 98c54fc5eac64ce2b717c39660faca77f90a1a9a Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 19:21:06 +0100 Subject: [PATCH 07/60] FIX: warning: specified bound depends on the length of the source argument --- src/os/posix/host-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/posix/host-lib.c b/src/os/posix/host-lib.c index db72831987..d7b35a7a26 100644 --- a/src/os/posix/host-lib.c +++ b/src/os/posix/host-lib.c @@ -504,7 +504,7 @@ RL_LIB *RL; // Link back to reb-lib from embedded extensions (like for now: host return len + 1; } - COPY_STR(envval, value, len); + COPY_STR(envval, value, valsize); return len; } From a38e2a5c5622641df7ca291a396d4937f871e589 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 19:23:18 +0100 Subject: [PATCH 08/60] FEAT: added possibility to set/clear BRK, RTS and DTR serial port flags on Posix --- src/os/posix/dev-serial.c | 42 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/os/posix/dev-serial.c b/src/os/posix/dev-serial.c index c5c5a53ff0..0baf61647e 100644 --- a/src/os/posix/dev-serial.c +++ b/src/os/posix/dev-serial.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -318,6 +319,45 @@ static REBOOL Set_Serial_Settings(int ttyfd, REBREQ *req) return DR_DONE; } +/*********************************************************************** +** +*/ DEVICE_CMD Modify_Serial(REBREQ *req) +/* +***********************************************************************/ +{ + REBOOL value = req->modify.value; + int status; + int mode = req->modify.mode; + + if (!req->id) { + req->error = -RFE_NO_HANDLE; + return DR_ERROR; + } + + if (mode == 1) { + ioctl(req->id, value ? TIOCSBRK : TIOCCBRK); + return DR_DONE; + } + if (ioctl(req->id, TIOCMGET, &status) == -1) return DR_ERROR; + if (mode == 2) { + // (request-to-send) signal + if (value) { + status |= TIOCM_RTS; + } else { + status &= ~TIOCM_RTS; + } + } else { + // (data-terminal-ready) signal + if (value) { + status |= TIOCM_DTR; + } else { + status &= ~TIOCM_DTR; + } + } + if (ioctl(req->id, TIOCMSET, &status) == -1) return DR_ERROR; + return DR_DONE; +} + /*********************************************************************** ** @@ -335,7 +375,7 @@ static DEVICE_CMD_FUNC Dev_Cmds[RDC_MAX] = { 0, // poll 0, // connect Query_Serial, - 0, // modify + Modify_Serial, 0, // create 0, // delete 0 // rename From a84671a2d4477e51649884020e4e0993b438a003 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 19:34:50 +0100 Subject: [PATCH 09/60] =?UTF-8?q?FIX:=20warning:=20ignoring=20return=20val?= =?UTF-8?q?ue=20of=20=E2=80=98read=E2=80=99,=20declared=20with=20attribute?= =?UTF-8?q?=20warn=5Funused=5Fresult?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/os/posix/dev-stdio.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/os/posix/dev-stdio.c b/src/os/posix/dev-stdio.c index a2327cb653..4fc652e746 100644 --- a/src/os/posix/dev-stdio.c +++ b/src/os/posix/dev-stdio.c @@ -362,12 +362,13 @@ static void Close_StdIO_Local(void) if (c[0] == '\e') { evt.type = EVT_CONTROL; // Escape sequences... is there really some system in it?! + // This may be helpful: https://stackoverflow.com/a/71659748 if (poll(&poller, 1, 0) <= 0) { // no any other char evt.data = EVK_ESCAPE; goto throw_event; } - read(Std_Inp, &c, 2); + if (2 != read(Std_Inp, &c, 2)) break; //printf(" %s ", c); if (c[0] == '[') { switch(c[1]){ @@ -379,9 +380,10 @@ static void Close_StdIO_Local(void) case 'H': evt.data = EVK_HOME; goto throw_event; } if (c[1] == '1') { - read(Std_Inp, &c[2], 2); + if (2 != read(Std_Inp, &c[2], 2)) break; //printf("%s ", c); - if(c[3] == '~') { + if(c[3] == '~' || c[3] == '^') { + if (c[3] == '^') SET_FLAG(evt.flags, EVF_CONTROL); switch(c[2]){ case '1': evt.data = EVK_F1; goto throw_event; //== "\e[11~" case '2': evt.data = EVK_F2; goto throw_event; //== "\e[12~" @@ -395,7 +397,7 @@ static void Close_StdIO_Local(void) } else if(c[2] == ';' && c[3] == '2') { SET_FLAG(evt.flags, EVF_SHIFT); - read(Std_Inp, &c[4], 1); + if (1 != read(Std_Inp, &c[4], 1)) break; switch(c[4]){ case 'C': evt.data = EVK_RIGHT; goto throw_event; //== "\e[1;2C" case 'D': evt.data = EVK_LEFT; goto throw_event; //== "\e[1;2D" @@ -403,12 +405,12 @@ static void Close_StdIO_Local(void) } } else if (c[1] == '2') { - read(Std_Inp, &c[2], 1); + if (1 != read(Std_Inp, &c[2], 1)) break; //printf("%s ", c); if (c[2] == '~') { evt.data = EVK_INSERT; goto throw_event; //== "\e[2~" } - read(Std_Inp, &c[3], 1); + if (1 != read(Std_Inp, &c[3], 1)) break; //printf("%s ", c); if (c[3] == '~') { switch(c[2]){ @@ -425,8 +427,24 @@ static void Close_StdIO_Local(void) case '9': evt.data = EVK_F8; goto throw_event; } } + if (c[3] == '^') { + SET_FLAG(evt.flags, EVF_CONTROL); + switch(c[2]){ + case '0': evt.data = EVK_F9; goto throw_event; //== "\e[20^" + case '1': evt.data = EVK_F10; goto throw_event; + case '3': evt.data = EVK_F11; goto throw_event; + case '4': evt.data = EVK_F12; goto throw_event; + } + SET_FLAG(evt.flags, EVF_SHIFT); + switch(c[2]){ + case '5': evt.data = EVK_F5; goto throw_event; //== "\e[25^" + case '6': evt.data = EVK_F6; goto throw_event; + case '8': evt.data = EVK_F7; goto throw_event; + case '9': evt.data = EVK_F8; goto throw_event; + } + } else { - read(Std_Inp, &c[4], 1); + if (1 != read(Std_Inp, &c[4], 1)) break; if (c[4] == '~' && c[2] == '0') { switch(c[3]){ case '0': evt.data = EVK_PASTE_START; goto throw_event; //== "\e[200~" @@ -436,7 +454,7 @@ static void Close_StdIO_Local(void) } } else if (c[1] > '2' && c[1] <= '8') { - read(Std_Inp, &c[2], 1); + if (1 != read(Std_Inp, &c[2], 1)) break; //printf("%s ", c); if (c[2] == '~') { switch(c[1]){ @@ -449,7 +467,7 @@ static void Close_StdIO_Local(void) } } else if (c[1] == '3') { - read(Std_Inp, &c[3], 1); + if (1 != read(Std_Inp, &c[3], 1)) break; //printf("%s ", c); if (c[3] == '~') { SET_FLAG(evt.flags, EVF_SHIFT); @@ -483,7 +501,7 @@ static void Close_StdIO_Local(void) if ((c[0] & 0xE0) == 0xC0) len = 1; // `len` as a number of missing bytes! else if ((c[0] & 0xF0) == 0xE0) len = 2; else if ((c[0] & 0xF8) == 0xF0) len = 3; - read(Std_Inp, &c[1], len); + if (len != read(Std_Inp, &c[1], len)) break; evt.data = RL_Decode_UTF8_Char(c, &len); } throw_event: From 2ea23b1a25f076acaa3f0bdd662ffed58c869de6 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 20:33:54 +0100 Subject: [PATCH 10/60] =?UTF-8?q?FIX:=20ignore=20warning:=20=E2=80=98=5F?= =?UTF-8?q?=5Fbuiltin=5F=5F=5Fstrncpy=5Fchk=E2=80=99=20specified=20bound?= =?UTF-8?q?=20depends=20on=20the=20length=20of=20the=20source=20argument?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/os/posix/host-readline.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/os/posix/host-readline.c b/src/os/posix/host-readline.c index 52e95bb70d..92464a2e10 100644 --- a/src/os/posix/host-readline.c +++ b/src/os/posix/host-readline.c @@ -729,11 +729,14 @@ static struct termios Term_Attrs; // Initial settings, restored on exit // If we have leftovers: if (term->residue[0]) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" end = (int)LEN_BYTES(term->residue); if (end < len) len = end; COPY_STR(buf, term->residue, len); // terminated below - MOVE_MEM(term->residue, term->residue+len, end-len); // remove + COPY_MEM(term->residue, term->residue+len, end-len); // remove term->residue[end-len] = 0; +#pragma GCC diagnostic pop } else { // Read next few bytes. We don't know how many may be waiting. From 56a39e6267e828add4be1e5d2d1741a452b45128 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 29 Nov 2023 20:34:22 +0100 Subject: [PATCH 11/60] =?UTF-8?q?FIX:=20warning:=20implicit=20declaration?= =?UTF-8?q?=20of=20function=20=E2=80=98wcwidth=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/os/posix/host-readline.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/os/posix/host-readline.c b/src/os/posix/host-readline.c index 92464a2e10..452d0592d6 100644 --- a/src/os/posix/host-readline.c +++ b/src/os/posix/host-readline.c @@ -49,6 +49,8 @@ #include #include +int wcwidth(wchar_t wc); + #include "reb-c.h" //#define TEST_MODE // teset as stand-alone program From a730144ae9cb4d607d6725c5ea0044760e335c08 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 30 Nov 2023 13:20:39 +0100 Subject: [PATCH 12/60] FIX: accept block input to `call` function on Windows resolves: https://github.com/Oldes/Rebol-issues/issues/2582 --- src/os/win32/host-lib.c | 13 ++++++++++++- src/tests/units/call-test.r3 | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/os/win32/host-lib.c b/src/os/win32/host-lib.c index 2253d3c41c..1362e8e18f 100644 --- a/src/os/win32/host-lib.c +++ b/src/os/win32/host-lib.c @@ -1007,7 +1007,18 @@ void Dispose_Windows(void); if (call == NULL) { /* command in argv */ - goto cleanup; /* NOT IMPLEMENTED*/ + // count the length of the full command line... + size_t len = 1; // termination byte + for (int n = 0; n < argc; n++) { + len += wcslen(argv[n]) + 1; + } + cmd = cast(wchar_t*, malloc(len * sizeof(wchar_t))); + cmd[0] = L'\0'; + // construct the command line + for (int n = 0; n < argc; n++) { + wcscat(cmd, argv[n]); + wcscat(cmd, L" "); + } } else { if (flag_shell) { // command to cmd.exe needs to be surrounded by quotes to preserve the inner quotes diff --git a/src/tests/units/call-test.r3 b/src/tests/units/call-test.r3 index 16e38c8bfd..087951a835 100644 --- a/src/tests/units/call-test.r3 +++ b/src/tests/units/call-test.r3 @@ -18,7 +18,7 @@ rebol-cmd: func[cmd][ call/shell/wait/output/error cmd out-buffer err-buffer ] -===start-group=== "Command-Line Interface" +===start-group=== "Command-Line Interface (/shell)" ;@@ https://github.com/Oldes/Rebol-issues/issues/2228 --test-- "--do" ;@@ https://github.com/Oldes/Rebol-issues/issues/2467 @@ -75,6 +75,19 @@ rebol-cmd: func[cmd][ ===end-group=== +===start-group=== "Command-Line Interface" + --test-- "Block input" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2582 + --assert all [ + file? try [write %issue-2582.r3 {Rebol [] print now}] + tmp: clear "" + 0 = call/wait/output reduce [system/options/boot %issue-2582.r3] tmp + date? transcode/one tmp + ] + delete %issue-2582.r3 +===end-group=== + + ===start-group=== "Error pipe" --test-- "User controlled error output" ;@@ https://github.com/Oldes/Rebol-issues/issues/2468 From 39c7e22efb9237a1e86e72973ebf0582d3d5e981 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 30 Nov 2023 17:29:00 +0100 Subject: [PATCH 13/60] FEAT: allow any-string value as a `call` argument --- src/boot/natives.reb | 2 +- src/core/n-io.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/boot/natives.reb b/src/boot/natives.reb index 6714acb418..92de92c3ce 100644 --- a/src/boot/natives.reb +++ b/src/boot/natives.reb @@ -908,7 +908,7 @@ list-env: native [ call: native [ {Run another program; return immediately.} - command [string! block! file!] "An OS-local command line (quoted as necessary), a block with arguments, or an executable file" + command [any-string! block! file!] "An OS-local command line (quoted as necessary), a block with arguments, or an executable file" /wait "Wait for command to terminate before returning" /console "Runs command with I/O redirected to console" /shell "Forces command to be run from shell" diff --git a/src/core/n-io.c b/src/core/n-io.c index 1286dfddde..8d2a8bf601 100644 --- a/src/core/n-io.c +++ b/src/core/n-io.c @@ -791,7 +791,16 @@ static REBSER *Read_All_File(char *fname) if (flag_shell) flags |= FLAG_SHELL; if (flag_info) flags |= FLAG_INFO; - if (IS_STRING(arg)) { + if (IS_FILE(arg)) { + REBSER* ser = NULL; + REBSER* path = Value_To_OS_Path(arg, FALSE); + argc = 1; + ser = Make_Series(argc + 1, sizeof(REBCHR*), FALSE); + argv = (REBCHR**)SERIES_DATA(ser); + argv[0] = (REBCHR*)SERIES_DATA(path); + argv[argc] = NULL; + cmd = NULL; + } else if (ANY_STR(arg)) { REBSER * ser = NULL; cmd = Val_Str_To_OS(arg); argc = 1; @@ -810,26 +819,17 @@ static REBSER *Read_All_File(char *fname) argv = (REBCHR**)SERIES_DATA(ser); for (i = 0; i < argc; i ++) { REBVAL *param = VAL_BLK_SKIP(arg, i); - if (IS_STRING(param)) { + if (IS_FILE(param)) { + REBSER* path = Value_To_OS_Path(param, FALSE); + argv[i] = (REBCHR*)SERIES_DATA(path); + } else if (ANY_STR(param)) { argv[i] = Val_Str_To_OS(param); - } else if (IS_FILE(param)) { - REBSER *path = Value_To_OS_Path(param, FALSE); - argv[i] = (REBCHR*) SERIES_DATA(path); } else { Trap_Arg(param); } } argv[argc] = NULL; cmd = NULL; - } else if (IS_FILE(arg)) { - REBSER * ser = NULL; - REBSER *path = Value_To_OS_Path(arg, FALSE); - argc = 1; - ser = Make_Series(argc + 1, sizeof(REBCHR*), FALSE); - argv = (REBCHR**)SERIES_DATA(ser); - argv[0] = (REBCHR*) SERIES_DATA(path); - argv[argc] = NULL; - cmd = NULL; } else { Trap_Arg(arg); } From 963d083a5e7fbf2c96ef9a60be386af7ff4402c0 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 30 Nov 2023 17:46:39 +0100 Subject: [PATCH 14/60] FEAT: allow `word!`, `get-word!` and `get-path!` values inside a `call` argument --- src/core/n-io.c | 10 ++++++++++ src/tests/units/call-test.r3 | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/core/n-io.c b/src/core/n-io.c index 8d2a8bf601..4383fecb4a 100644 --- a/src/core/n-io.c +++ b/src/core/n-io.c @@ -819,11 +819,21 @@ static REBSER *Read_All_File(char *fname) argv = (REBCHR**)SERIES_DATA(ser); for (i = 0; i < argc; i ++) { REBVAL *param = VAL_BLK_SKIP(arg, i); + if (IS_GET_WORD(param)) { + param = Get_Var(param); + } + else if (IS_GET_PATH(param)) { + Do_Path(¶m, NULL); + param = DS_POP; // volatile stack reference + } if (IS_FILE(param)) { REBSER* path = Value_To_OS_Path(param, FALSE); argv[i] = (REBCHR*)SERIES_DATA(path); } else if (ANY_STR(param)) { argv[i] = Val_Str_To_OS(param); + } else if (IS_WORD(param)) { + Set_Series(REB_STRING, D_RET, Copy_Form_Value(param, TRUE)); + argv[i] = Val_Str_To_OS(D_RET); } else { Trap_Arg(param); } diff --git a/src/tests/units/call-test.r3 b/src/tests/units/call-test.r3 index 087951a835..87c97b6855 100644 --- a/src/tests/units/call-test.r3 +++ b/src/tests/units/call-test.r3 @@ -85,6 +85,17 @@ rebol-cmd: func[cmd][ date? transcode/one tmp ] delete %issue-2582.r3 + --test-- "Block input with word!, get-word! and get-path!" + --assert all [ + file? try [write %probe-args.r3 {Rebol [] probe system/options/args}] + tmp: clear "" + url: http://example.org + ;; not using reduce in this test... + 0 = call/wait/output [:system/options/boot %probe-args.r3 :url foo] tmp + ["http://example.org" "foo"] = transcode/one tmp + ] + delete %probe-args.r3 + ===end-group=== From 76ce93b1376ed0096ceb112cd0c829efb20ea32c Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 30 Nov 2023 22:42:44 +0100 Subject: [PATCH 15/60] Included comment --- src/core/n-io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/n-io.c b/src/core/n-io.c index 4383fecb4a..93ecadf2e2 100644 --- a/src/core/n-io.c +++ b/src/core/n-io.c @@ -819,6 +819,7 @@ static REBSER *Read_All_File(char *fname) argv = (REBCHR**)SERIES_DATA(ser); for (i = 0; i < argc; i ++) { REBVAL *param = VAL_BLK_SKIP(arg, i); + // to avoid call to reduce, resolve get-word! or get-path! values if used if (IS_GET_WORD(param)) { param = Get_Var(param); } From bf49996cccaec38302cd6481856bc63dd0ed6bb4 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 30 Nov 2023 23:24:38 +0100 Subject: [PATCH 16/60] CHANGE: modified `launch` function not to use shell and to handle all optional script arguments --- src/mezz/mezz-control.reb | 31 ++++++++++++++++++++----------- src/tests/units/call-test.r3 | 9 +++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/mezz/mezz-control.reb b/src/mezz/mezz-control.reb index e258e06b97..54d2542866 100644 --- a/src/mezz/mezz-control.reb +++ b/src/mezz/mezz-control.reb @@ -11,20 +11,29 @@ REBOL [ } ] -launch: func [ +launch: function/with [ {Runs a script as a separate process; return immediately.} - script [file! string! none!] "The name of the script" - /args arg [string! block! none!] "Arguments to the script" + script [file! string!] "The name of the script" + /with args [string! block! none!] "Arguments to the script" /wait "Wait for the process to terminate" - /local exe ][ - if file? script [script: to-local-file any [to-real-file script script]] - exe: to-local-file system/options/boot - - ; Quote everything, just in case it has spaces: - args: to-string reduce [{"} exe {" "} script {" }] - if arg [append args arg] - either wait [call/wait/shell args] [call/shell args] + command: reduce [system/options/boot script] + if args [ + unless block? args [args: reduce [:args]] + foreach arg args [ + ;; arguments are expected to be strings... + append command escape-arg mold/flat arg + ] + ] + sys/log/info 'REBOL ["Launch:" as-green reform next command] + call/:wait command +][ + ;-- just a simple argument escaping function + ;@@ needs test on other platforms... Linux seems to be ok without any escaping. + escape-arg: func[arg] either/only system/platform = 'Windows [ + replace/all arg #"^"" {\"} + append insert arg #"^"" #"^"" + ][ arg ] ] wrap: func [ diff --git a/src/tests/units/call-test.r3 b/src/tests/units/call-test.r3 index 87c97b6855..8953fc12d0 100644 --- a/src/tests/units/call-test.r3 +++ b/src/tests/units/call-test.r3 @@ -127,6 +127,15 @@ rebol-cmd: func[cmd][ --assert 0:0:2 < delta-time [do %units/files/launch-wait.r3] ;; should wait --assert 6 = try [length? read/lines %units/files/launched.txt] ;; 6 because 3x launched! + --test-- "do launch/with" + --assert all [ + file? write %args.r3 {Rebol[] args: system/options/args forall args [args/1: transcode/one args/1] save %temp args} + 0 == launch/with/wait %args.r3 args: [2 {a "b" c} %"foo space"] + args == load %temp + ] + delete %temp + delete %args.r3 + try [delete %units/files/launched.txt] ===end-group=== From b0f6840ceb23f0f7752f9f7edae25edaced34bbe Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 8 Dec 2023 17:22:02 +0100 Subject: [PATCH 17/60] FIX: reading from virtual `/proc` files on Linux using `read/part` resolves: https://github.com/Oldes/Rebol-issues/issues/2303 --- src/core/p-file.c | 6 +++++- src/tests/units/port-test.r3 | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/core/p-file.c b/src/core/p-file.c index d98954970f..6e9e917ff3 100644 --- a/src/core/p-file.c +++ b/src/core/p-file.c @@ -405,7 +405,11 @@ REBINT Mode_Syms[] = { len += cnt; SET_FLAG(file->modes, RFM_RESEEK); } - if (cnt > len) return (REBCNT)len; + // Originaly, when the requested part was larger then the reported file's size, + // then the reported file size was used instead. But on Posix there are virtual files, + // where the size is reported as 0. In this case we keep the user's requested length. + // See: https://github.com/Oldes/Rebol-issues/issues/2303 + if (cnt > len && len > 0) return (REBCNT)len; return (REBCNT)cnt; } diff --git a/src/tests/units/port-test.r3 b/src/tests/units/port-test.r3 index ebcb0a2851..59ae60884b 100644 --- a/src/tests/units/port-test.r3 +++ b/src/tests/units/port-test.r3 @@ -524,6 +524,27 @@ if system/platform = 'Windows [ --assert all [error? e: try [append/only p "aa"] e/id = 'bad-refines] try [delete %issue-1894] +if exists? %/proc/cpuinfo [ + --test-- "Reading from /proc files on Linux" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2303 + --assert all [ + not error? info: try [read/string %/proc/cpuinfo] + empty? info ;; empty, because to read this type of file, the size must be specified! + ] + --assert all [ + not error? info: try [read/string/part %/proc/cpuinfo 10000] + print info + 0 < length? info + ] +] + --test-- "Reading an empty file" + --assert all [ + file? write %empty "" + 0 = length? read %empty + 0 = length? read/part %empty 1000 + port? delete %empty + ] + ===end-group=== if system/platform = 'Windows [ From 33791985d066c1ccec7f816bf8cea08179629c12 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 8 Dec 2023 17:38:48 +0100 Subject: [PATCH 18/60] Fixed typo. --- src/core/p-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/p-file.c b/src/core/p-file.c index 6e9e917ff3..ea21bacaa6 100644 --- a/src/core/p-file.c +++ b/src/core/p-file.c @@ -405,7 +405,7 @@ REBINT Mode_Syms[] = { len += cnt; SET_FLAG(file->modes, RFM_RESEEK); } - // Originaly, when the requested part was larger then the reported file's size, + // Originaly, when the requested part was larger than the reported file's size, // then the reported file size was used instead. But on Posix there are virtual files, // where the size is reported as 0. In this case we keep the user's requested length. // See: https://github.com/Oldes/Rebol-issues/issues/2303 From 8ee972c64ef81df1f58e42e31d7876c6635a8c2a Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Mon, 11 Dec 2023 15:13:34 +0100 Subject: [PATCH 19/60] FIX: `bbcode` codec must convert binary input to string before decoding --- src/mezz/codec-bbcode.reb | 11 +++++++---- src/tests/units/bbcode-test.r3 | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index 538fefe245..56f8146046 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -2,7 +2,7 @@ REBOL [ Name: bbcode Type: module Options: [delay] - Version: 0.3.0 + Version: 0.3.1 Title: "Codec: BBcode" Purpose: {Basic BBCode implementation. For more info about BBCode check http://en.wikipedia.org/wiki/BBCode} File: https://raw.githubusercontent.com/Oldes/Rebol3/master/src/mezz/codec-bbcode.reb @@ -13,6 +13,7 @@ REBOL [ 0.2.0 19-Feb-2012 "review" 0.2.1 22-Aug-2012 "added [hr] and [anchor]" 0.3.0 24-Apr-2020 "ported to Rebol3" + 0.3.1 11-Dec-2023 "FIX: `bbcode` must accept only string input" ] ] @@ -195,7 +196,7 @@ enabled-tags: [ bbcode: func [ "Converts BBCode markup into HTML" - code [string! binary!] "Input with BBCode tags" + code [string!] "Input with BBCode tags" /local tag err ][ err: try [ @@ -438,8 +439,10 @@ register-codec [ /local result return: [string!] ][ - if any [file? code url? code][code: read code] + switch type?/word code [ + binary! [code: to string! code] + file! url! [code: read/string code] + ] result: bbcode code - ] ] \ No newline at end of file diff --git a/src/tests/units/bbcode-test.r3 b/src/tests/units/bbcode-test.r3 index 8c65b6b7f1..8affb4985a 100644 --- a/src/tests/units/bbcode-test.r3 +++ b/src/tests/units/bbcode-test.r3 @@ -88,6 +88,9 @@ if find codecs 'BBCode [ print "---" ] ] +--test-- "bbcode with binary input" + src: {text [b]bold[/b] abc} + --assert (decode 'bbcode srt) = (decode 'bbcode to binary! src) ===end-group=== ] From e39581578b98b3eeb121f47e99224e8dda2be424 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Tue, 12 Dec 2023 18:17:45 +0100 Subject: [PATCH 20/60] FEAT: `bbcode` csv table emitter --- src/mezz/codec-bbcode.reb | 73 ++++++++++++++++++++++++++++++++-- src/tests/units/bbcode-test.r3 | 21 +++++++++- 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index 56f8146046..7be79bc0cc 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -2,7 +2,7 @@ REBOL [ Name: bbcode Type: module Options: [delay] - Version: 0.3.1 + Version: 0.3.2 Title: "Codec: BBcode" Purpose: {Basic BBCode implementation. For more info about BBCode check http://en.wikipedia.org/wiki/BBCode} File: https://raw.githubusercontent.com/Oldes/Rebol3/master/src/mezz/codec-bbcode.reb @@ -13,7 +13,8 @@ REBOL [ 0.2.0 19-Feb-2012 "review" 0.2.1 22-Aug-2012 "added [hr] and [anchor]" 0.3.0 24-Apr-2020 "ported to Rebol3" - 0.3.1 11-Dec-2023 "FIX: `bbcode` must accept only string input" + 0.3.1 11-Dec-2023 "FIX: `bbcode` must accept only string input"\ + 0.3.2 12-Dec-2023 "FEAT: csv table emitter" ] ] @@ -39,6 +40,7 @@ ch_digits: charset [#"0" - #"9"] ch_hexa: charset [#"a" - #"f" #"A" - #"F" #"0" - #"9"] ch_name: charset [#"a" - #"z" #"A" - #"Z" #"*" #"0" - #"9"] ch_url: charset [#"a" - #"z" #"A" - #"Z" #"0" - #"9" "./:~+-%#\_=&?@"] +ch_crlf: charset CRLF ch_safe-value-chars: complement charset {'"} rl_newline: [CRLF | LF] @@ -188,6 +190,69 @@ emit-tag: func[tag][ insert tail html either block? tag [rejoin tag][tag] ] +emit-tag-csv: function/with [spec [string!]][ + row: "" ;; no copy, it is cleared each time + trim/head/tail spec + + close-p-if-possible + close-tags + emit-tag [{^/}] + all [ + widths: get-attribute "widths" + widths: transcode widths + ] + if align: get-attribute "coltype" [ + parse align [ + some [ + #"c" (emit-tag {^/}) + | #"l" (emit-tag {^/}) + | #"r" (emit-tag {^/}) + | #"j" (emit-tag {^/}) + ] + ] + ] + ch_divider: charset get-attribute/default "divider" TAB + ch_notDivider: complement union ch_divider ch_crlf + rl_data: [copy data any ch_notDivider] + + data: align: none + row-num: col-num: col-width: 0 + datatag: "th" ;; first row is always used for headers! + parse spec [ + some [ + ( + clear row + ++ row-num + ) + any ch_space + some [ + rl_data + 1 ch_divider + ( + append row ajoin [{<} datatag get-col-width {>} data {}] + ) + ] + rl_data [rl_newline | end] ( + append row ajoin [{<} datatag get-col-width {>} data {}] + datatag: "td" + emit-tag ["" row "^/"] + ) + ] + ] + emit-tag "" +] [ + data: widths: align: row-num: col-num: col-width: none + get-col-width: does [ + ++ col-num + either all [ + row-num = 1 + block? widths + col-width: pick widths col-num + integer? col-width + ][ ajoin [" width=" col-width] ][ "" ] + ] +] + enabled-tags: [ "b" "i" "s" "u" "del" "h1" "h2" "h3" "h4" "h5" "h6" "span" "class" "ins" "dd" "dt" "ol" "ul" "li" "url" "list" "br" "hr" @@ -414,8 +479,8 @@ bbcode: func [ ] unless empty? opened-tags [ close-tags ] html - ] - if error? err [ + ][ + err: system/state/last-error ; send possible trimmed error in the result instead of throwing it! append html ajoin ["^/#[ERROR! [code: " err/code " type: " err/type " id: " err/id #"]"] ] diff --git a/src/tests/units/bbcode-test.r3 b/src/tests/units/bbcode-test.r3 index 8affb4985a..8b6aa9906e 100644 --- a/src/tests/units/bbcode-test.r3 +++ b/src/tests/units/bbcode-test.r3 @@ -77,6 +77,25 @@ if find codecs 'BBCode [ {[hr10%]} {


} {[anchor]foo[/anchor]} {

} {[class=underline]foo} {

foo

} + {[csv class=vysledky] +name number position +foo 1 2 +boo 2 1 +[/csv]} { + + + +
namenumberposition
foo12
boo21
} + + {[csv divider=';' align='center' coltype='lcr' widths='100 20 *'] +name;number;position +[/csv]} +{ ++++ +
namenumberposition
} ] bbcode: :codecs/bbcode/decode foreach [src result] test-cases [ @@ -90,7 +109,7 @@ if find codecs 'BBCode [ ] --test-- "bbcode with binary input" src: {text [b]bold[/b] abc} - --assert (decode 'bbcode srt) = (decode 'bbcode to binary! src) + --assert (decode 'bbcode src) = (decode 'bbcode to binary! src) ===end-group=== ] From ffa41e0b0d48cc5371e32215c35b3a2d73d47149 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 14 Dec 2023 10:17:34 +0100 Subject: [PATCH 21/60] FEAT: `bbcode` image gallery emitter --- src/mezz/codec-bbcode.reb | 93 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index 7be79bc0cc..d52f0c6fc1 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -2,19 +2,20 @@ REBOL [ Name: bbcode Type: module Options: [delay] - Version: 0.3.2 + Version: 0.3.3 Title: "Codec: BBcode" Purpose: {Basic BBCode implementation. For more info about BBCode check http://en.wikipedia.org/wiki/BBCode} File: https://raw.githubusercontent.com/Oldes/Rebol3/master/src/mezz/codec-bbcode.reb - Date: 24-Apr-2020 + Date: 13-Dec-2023 Author: "Oldes" History: [ 0.1.0 5-Jan-2009 "initial version" 0.2.0 19-Feb-2012 "review" 0.2.1 22-Aug-2012 "added [hr] and [anchor]" 0.3.0 24-Apr-2020 "ported to Rebol3" - 0.3.1 11-Dec-2023 "FIX: `bbcode` must accept only string input"\ + 0.3.1 11-Dec-2023 "FIX: `bbcode` must accept only string input" 0.3.2 12-Dec-2023 "FEAT: csv table emitter" + 0.3.3 13-Dec-2023 "FEAT: image gallery emitter" ] ] @@ -253,6 +254,90 @@ emit-tag-csv: function/with [spec [string!]][ ] ] +;-- like: [images dir="foto/" alt="some text" maxWidth=680] +emit-tag-images: function/with [][ + close-tags + if attr [repend attributes ["dir" copy attr]] + ;; maximum allowed width of the image (width of the gallery) + max-width: to integer! any [get-attribute "width" get-attribute "maxWidth" 680] + ;; requested height of images on the row (may be higher!) + row-height: to integer! any [get-attribute "height" get-attribute "rowHeight" 300] + ;; requested spacing between images on the row (may differ) + space: get-attribute/default "space" 6 + alt: get-attribute/default "alt" "" + unless empty? alt [insert alt SP] + + columns: num: 0 + temp: clear [] + files: none + dir: to-rebol-file get-attribute "dir" + files: read dir + + foreach file files [ + if any [ + ;use only jpegs... + none? find file %.jpg + ;don't use files with names like: photo_150x.jpg or photo_x150.jpg or photo_150x150.jpg + parse any [find/last file #"_" ""][ + #"_" any ch_digits #"x" any ch_digits #"." to end + ] + ][continue] + + img: load dir/:file + size: img/size + w: size/x + h: size/y + rw: to integer! (w * (row-height / h)) + size-scaled: as-pair rw row-height + + bgimg: enbase encode 'png resize img 6x3 64 + replace/all bgimg LF "" + + ++ num + + row-width: row-width + rw + space + title: ajoin [num #"." alt] + either row-width > (1.5 * max-width) [ ;; the value 1.5 is there to get more images on a row (which is then scaled down) + row-width: row-width - rw - space + emit-row + row-width: rw + columns: 1 + append temp reduce [file size size-scaled bgimg title] + ][ + ++ columns + append temp reduce [file size size-scaled bgimg title] + ] + ] + if columns > 0 [emit-row] +][ + temp: clear [] + dir: files: none + max-width: row-width: 0 + + emit-img: func[ + bgimg file size title + /local nw nh + ][ + nw: to integer! size/x + nh: to integer! size/y + append html ajoin [ + {^/
} + {} + {} title {
} + ] + ] + emit-row: func[/local scale][ + ;; the final row is scaled to fit the maximal width + scale: max-width / row-width + append html "^/
" + foreach [file size size-scaled bgimg title] temp [ + emit-img bgimg file size-scaled * scale title + ] + append html "^/
" + clear temp + ] +] + enabled-tags: [ "b" "i" "s" "u" "del" "h1" "h2" "h3" "h4" "h5" "h6" "span" "class" "ins" "dd" "dt" "ol" "ul" "li" "url" "list" "br" "hr" @@ -480,7 +565,7 @@ bbcode: func [ unless empty? opened-tags [ close-tags ] html ][ - err: system/state/last-error + probe err: system/state/last-error ; send possible trimmed error in the result instead of throwing it! append html ajoin ["^/#[ERROR! [code: " err/code " type: " err/type " id: " err/id #"]"] ] From 051670ad6e5b2ec6cee6e95c002a43a06f128a97 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 16 Dec 2023 00:53:22 +0100 Subject: [PATCH 22/60] FIX: using correct path to images in the generated `bbcode` image gallery --- src/mezz/codec-bbcode.reb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index d52f0c6fc1..4b285a5c29 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -283,7 +283,7 @@ emit-tag-images: function/with [][ ] ][continue] - img: load dir/:file + img: load path: to-relative-file dir/:file size: img/size w: size/x h: size/y @@ -302,10 +302,10 @@ emit-tag-images: function/with [][ emit-row row-width: rw columns: 1 - append temp reduce [file size size-scaled bgimg title] + append temp reduce [path size size-scaled bgimg title] ][ ++ columns - append temp reduce [file size size-scaled bgimg title] + append temp reduce [path size size-scaled bgimg title] ] ] if columns > 0 [emit-row] From 7a9e11000d4275e95940116593ec0a731289d5e0 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 16 Dec 2023 02:23:31 +0100 Subject: [PATCH 23/60] CHANGE: updated `httpd` scheme to version 0.9.0 --- src/modules/httpd.reb | 245 +++++++++++++++++++++++++++------------- src/modules/spotify.reb | 42 +++---- src/tests/test-httpd.r3 | 58 ++-------- 3 files changed, 197 insertions(+), 148 deletions(-) diff --git a/src/modules/httpd.reb b/src/modules/httpd.reb index 0d4a563e33..760ec06cb2 100644 --- a/src/modules/httpd.reb +++ b/src/modules/httpd.reb @@ -1,11 +1,11 @@ Rebol [ - Title: "HTTPD Scheme" + Title: "HTTPd Scheme" Type: module Name: httpd - Date: 23-Jun-2023 - Version: 0.8.2 + Date: 14-Dec-2023 + Version: 0.9.0 Author: ["Andreas Bolka" "Christopher Ross-Gill" "Oldes"] - Exports: [http-server decode-target to-CLF-idate] + Exports: [serve-http http-server decode-target to-CLF-idate] Home: https://github.com/Oldes/Rebol-HTTPd Rights: http://opensource.org/licenses/Apache-2.0 Purpose: { @@ -35,6 +35,7 @@ Rebol [ 06-Dec-2022 "Oldes" {Added minimal support for WebSocket connections} 09-Jan-2023 "Oldes" {New home: https://github.com/Oldes/Rebol-HTTPd} 09-May-2023 "Oldes" {Root-less configuration possibility (default)} + 14-Dec-2023 "Oldes" {Deprecated the `http-server` function in favor of `serve-http` with a different configuration input} ] Needs: [3.11.0 mime-types] ] @@ -149,7 +150,7 @@ decode-multipart-data: func[ boundary-end: join "^M^/--" boundary result: copy [] - probe parse data [ + parse data [ any [ "--" boundary CRLF (header: copy []) @@ -202,7 +203,7 @@ sys/make-scheme [ Actor: [ Open: func [port [port!] /local spec][ spec: port/spec - sys/log/info 'HTTPD ["Opening server at port:^[[22m" spec/port] + log-more ["Opening server at port:^[[22m" spec/port] port/extra: make object! [ subport: open compose [ scheme: 'tcp @@ -215,11 +216,11 @@ sys/make-scheme [ clients: make block! 16 ] subport/extra/config: - config: make object! [ - root: none - index: [%index.html %index.htm] - keep-alive: true - list-dir?: true + config: make map! [ + root: #[none] + index: [%index.html %index.htm] + keep-alive: #[true] + list-dir?: #[true] server-name: "Rebol3-HTTPd" ] ] @@ -229,7 +230,7 @@ sys/make-scheme [ ] Close: func [port [port!]][ - sys/log/info 'HTTPD ["Closing server at port:^[[22m" port/spec/port] + log-more ["Closing server at port:^[[22m" port/spec/port] close port/extra/subport ] @@ -241,6 +242,10 @@ sys/make-scheme [ /local target path info index modified If-Modified-Since ][ target: ctx/inp/target + unless ctx/config/root [ + Actor/On-Not-Found ctx target + exit + ] target/file: path: join ctx/config/root next clean-path/only target/file ctx/out/header/Date: to-idate/gmt now ctx/out/status: 200 @@ -249,7 +254,7 @@ sys/make-scheme [ foreach file ctx/config/index [ if exists? index: path/:file [ path: index - sys/log/debug 'HTTPD ["using index file:" index] + log-debug ["using index file:" index] break ] ] @@ -285,7 +290,12 @@ sys/make-scheme [ ] ] - On-Post: func[ctx [object!] /local content header length type temp][ + On-Post: func [ctx [object!]][ + ;@@ this is just a placeholder! + true + ] + + On-Read-Post: func[ctx [object!] /local content header length type temp][ ;@@ TODO: handle `Expect` header: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20 header: ctx/inp/header length: select header 'Content-Length @@ -322,23 +332,18 @@ sys/make-scheme [ ctx/inp/content: to string! content ] ] - Actor/On-Post-Received ctx + Actor/On-Post ctx ] ] - On-Post-Received: func [ctx [object!]][ - ;@@ this is just a placeholder! - true - ] - On-Read: func[ "Process READ action on client's port" ctx [object!] ][ switch/default ctx/inp/method [ - "HEAD" ; same like GET, but without sending content + "HEAD" ; same like GET, but without sending any content "GET" [ Actor/on-get ctx ] - "POST" [ Actor/on-post ctx ] + "POST" [ Actor/on-read-post ctx ] ][ ctx/state: 'data-received ctx/out/status: 405 ; Method Not Allowed @@ -353,11 +358,31 @@ sys/make-scheme [ ][ ;@@ this is just a placeholder! ] + On-Close-Websocket: func[ - "Process READ action on client's port using websocket" + "Process CLOSE action on client's port using websocket" ctx [object!] code [integer!] + /local reason ][ - ;@@ this is just a placeholder! + reason: any [ + select [ + 1000 "the purpose for which the connection was established has been fulfilled." + 1001 "a browser navigated away from a page." + 1002 "a protocol error." + 1003 "it has received a type of data it cannot accept." + 1007 "it has received data within a message that was not consistent with the type of the message." + 1008 "it has received a message that violates its policy." + 1009 "it has received a message that is too big for it to process." + 1010 "it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake." + 1011 "it encountered an unexpected condition that prevented it from fulfilling the request." + ] code + ajoin ["an unknown reason (" code ")"] + ] + log-info ["WS connection is closing because" reason] + unless empty? reason: ctx/inp/content [ + ;; optional client's reason + log-info ["Client's reason:" as-red to string! reason] + ] ] On-List-Dir: func[ @@ -365,7 +390,7 @@ sys/make-scheme [ /local path dir out size date files dirs ][ unless ctx/config/list-dir? [ - sys/log/more 'HTTPD ["Listing dir not allowed:^[[1m" mold target/file] + log-more ["Listing dir not allowed:^[[1m" mold target/file] ctx/out/status: 404 ; using not-found response! return false ] @@ -413,7 +438,7 @@ sys/make-scheme [ ] On-Not-Found: func[ctx [object!] target [object!]][ - sys/log/more 'HTTPD ["Target not found:^[[1m" mold target/file] + log-more ["Target not found:^[[1m" mold target/file] ctx/out/status: 404 ] @@ -496,7 +521,8 @@ sys/make-scheme [ Respond: function [port [port!]][ ctx: port/extra out: ctx/out - sys/log/info 'HTTPD ["Respond:^[[22m" out/status status-codes/(out/status) length? out/content] + unless out/status [out/status: 200] ;; expect OK response if not set + log-more ["Respond:^[[22m" out/status status-codes/(out/status) length? out/content] ; send the response header buffer: make binary! 1024 append buffer ajoin ["HTTP/" ctx/inp/version #" " out/status #" " status-codes/(out/status) CRLF] @@ -557,14 +583,13 @@ sys/make-scheme [ try/with [ write port buffer ][ - ;@@TODO: handle it without `print`; using on-error? - print "** Write failed!" + log-error "Write failed!" ;probe copy/part buffer 100 Awake-Client make event! [type: 'close port: port ] ] ] - Do-log: function [ctx][ + Write-log: function [ctx][ try/with [ msg: ajoin [ ctx/remote-ip @@ -577,18 +602,18 @@ sys/make-scheme [ #"^/" ] prin msg - if file? file: select ctx/config 'log-access [ + if file? file: ctx/config/log-access [ write/append file msg ] if all [ ctx/out/status >= 400 - file? file: select ctx/config 'log-errors + file? file: ctx/config/log-errors ][ write/append file msg ] ][ - print "** Failed to write a log" - print system/state/last-error + log-error "Failed to write a log" + log-error system/state/last-error ] ] @@ -606,13 +631,13 @@ sys/make-scheme [ inp: ctx/inp out: ctx/out - sys/log/more 'HTTPD ["Awake:^[[1m" ctx/remote "^[[22m" event/type] + log-more ["Awake:^[[1m" ctx/remote "^[[22m" event/type] ctx/timeout: now + 0:0:15 switch event/type [ READ [ - sys/log/more 'HTTPD ["bytes:^[[1m" length? port/data] + log-more ["bytes:^[[1m" length? port/data] either header-end: find/tail port/data CRLF2BIN [ try/with [ if none? ctx/state [ @@ -632,7 +657,7 @@ sys/make-scheme [ ] content: header-end ] - sys/log/info 'HTTPD ["Request header:^[[22m" ctx/inp/method mold ctx/inp/header] + log-more ["Request header:^[[22m" ctx/inp/method mold ctx/inp/header] ; on-header actor may be used for rewrite rules (redirection) actor/on-header ctx if ctx/out/status [ @@ -643,11 +668,11 @@ sys/make-scheme [ ] actor/on-read port/extra ][ - print system/state/last-error + log-error system/state/last-error ctx/state: 'error ctx/out/status: 500 ; Internal Server Error ] - sys/log/debug 'HTTPD ["State:^[[1m" ctx/state "^[[22mstatus:^[[1m" out/status] + log-debug ["State:^[[1m" ctx/state "^[[22mstatus:^[[1m" out/status] either ctx/state = 'read-data [ ; posted data not fully read read port @@ -675,7 +700,7 @@ sys/make-scheme [ try/with [ write port buffer ][ - print "** Write failed (2)!" + log-error "Write failed (2)!" ;probe buffer End-Client port ] @@ -696,7 +721,7 @@ sys/make-scheme [ port ] CLOSE [ - sys/log/info 'HTTPD ["Closing:^[[22m" ctx/remote] + log-more ["Closing:^[[22m" ctx/remote] if pos: find ctx/parent/extra/clients port [ remove pos ] close port ] @@ -705,7 +730,7 @@ sys/make-scheme [ ] Awake-Server: func [event [event!] /local ctx client config] [ - sys/log/debug 'HTTPD ["Awake (server):^[[22m" event/type] + log-debug ["Awake (server):^[[22m" event/type] switch event/type [ ACCEPT [ New-Client event/port ] CLOSE [ @@ -722,7 +747,7 @@ sys/make-scheme [ port: event/port ctx: port/extra - sys/log/more 'HTTPD ["Awake Websocket:^[[1m" ctx/remote "^[[22m" event/type] + log-more ["Awake Websocket:^[[1m" ctx/remote "^[[22m" event/type] ctx/timeout: now + 0:0:30 @@ -730,13 +755,13 @@ sys/make-scheme [ READ [ ready?: false data: head port/data - sys/log/more 'HTTPD ["bytes:^[[1m" length? data] + log-more ["bytes:^[[1m" length? data] try/with [ while [2 < length? data][ - final?: data/1 & 128 = 128 - opcode: data/1 & 15 - mask?: data/2 & 128 = 128 - len: data/2 & 127 + final?: data/1 & 2#10000000 = 2#10000000 + opcode: data/1 & 2#00001111 + mask?: data/2 & 2#10000000 = 2#10000000 + len: data/2 & 2#01111111 data: skip data 2 ;? final? ? opcode ? len @@ -764,14 +789,14 @@ sys/make-scheme [ ready?: true ctx/inp/content: truncate/part request-data len if opcode = 8 [ - sys/log/more 'HTTPD "WS Connection Close Frame!" + log-more "WS Connection Close Frame!" code: 0 if all [ 2 <= len 2 <= length? request-data ][ code: to integer! take/part request-data 2 - sys/log/more 'HTTPD ["WS Close reason:" as-red code] + log-more ["WS Close reason:" as-red code] ] actor/On-Close-Websocket ctx code event/type: 'CLOSE @@ -781,7 +806,7 @@ sys/make-scheme [ actor/On-Read-Websocket ctx final? opcode ] ][ - print system/state/last-error + log-error system/state/last-error ] either ready? [ ;; there was complete input... @@ -811,7 +836,7 @@ sys/make-scheme [ read port ] CLOSE [ - sys/log/info 'HTTPD ["Closing:^[[22m" ctx/remote] + log-more ["Closing:^[[22m" ctx/remote] if pos: find ctx/parent/extra/clients port [ remove pos ] close port ] @@ -824,7 +849,7 @@ sys/make-scheme [ info: query client unless Actor/On-Accept info [ ; connection not allowed - sys/log/info 'HTTPD ["Client not accepted:^[[22m" info/remote-ip] + log-more ["Client not accepted:^[[22m" info/remote-ip] close client return false ] @@ -857,16 +882,16 @@ sys/make-scheme [ client/extra/config: port/extra/config append port/extra/clients client - sys/log/info 'HTTPD ["New client:^[[1;31m" client/extra/remote] + log-more ["New client:^[[1;31m" client/extra/remote] try/with [read client][ - print ["** Failed to read new client:" client/extra/remote] - print system/state/last-error + log-error ["Failed to read new client:" client/extra/remote] + log-error system/state/last-error ] ] End-Client: function [port [port!]][ ctx: port/extra - Do-log ctx + Write-log ctx clients: ctx/parent/extra/clients keep-alive: ctx/config/keep-alive @@ -877,7 +902,7 @@ sys/make-scheme [ "close" <> select port/extra/inp/Header 'Connection ; client don't want or cannot handle persistent connection ][ ctx/requests: ctx/requests + 1 - sys/log/info 'HTTPD ["Keep-alive:^[[22m" ctx/remote "requests:" ctx/requests] + log-more ["Keep-alive:^[[22m" ctx/remote "requests:" ctx/requests] ; reset client state foreach v ctx/inp [ctx/inp/:v: none] foreach v ctx/out [ctx/out/:v: none] @@ -891,9 +916,9 @@ sys/make-scheme [ Awake-Client make event! [type: 'CLOSE port: port] ;try [remove find clients port] ] - sys/log/debug 'HTTPD ["Ports open:" length? clients] + log-debug ["Ports open:" length? clients] if all [ctx/done? zero? length? clients][ - sys/log/info 'HTTPD "Server's job done, closing initiated" + log-more "Server's job done, closing initiated" ctx/parent/data: ctx/done? Awake-Server make event! [type: 'CLOSE port: ctx/parent] ] @@ -904,10 +929,10 @@ sys/make-scheme [ port [port!] /local tm tmc ][ tm: now - ;sys/log/debug 'HTTPD ["Check-Clients:" length? port/state #"-" now] + ;log-debug ["Check-Clients:" length? port/state #"-" now] if block? port/state [ foreach client reverse copy port/state [ - ;sys/log/debug 'HTTPD ["Checking:" client/extra/remote client/extra/timeout] + ;log-debug ["Checking:" client/extra/remote client/extra/timeout] try [ if all [ date? tmc: client/extra/timeout @@ -919,10 +944,43 @@ sys/make-scheme [ ] ] ] + + anti-hacking-rules: [ + some [ + ;; common scripts, which we don't use + #"." [ + %php + | %aspx + | %cgi + ][end | #"?" | #"#"] reject + ; common hacking attempts to root folders... + | #"/" [ + %ecp/ ; we are not an exchange server + | %mifs/ ; either not MobileIron (https://stackoverflow.com/questions/67901776/what-does-the-line-mifs-services-logservice-mean) + | %GponForm/ ; nor Gpon router (https://www.vpnmentor.com/blog/critical-vulnerability-gpon-router/) + | %.env end ; https://stackoverflow.com/questions/64109005/do-these-env-get-requests-from-localhost-indicate-an-attack + ] reject + | 1 skip + ] + ] + + ;===================================================================== + log-error: log-info: log-more: log-debug: none + set-verbose: func[verbose [integer!]][ + log-error: log-info: log-more: log-debug: none + case/all [ + verbose >= 0 [log-error: func[msg][sys/log/error 'HTTPD :msg]] + verbose >= 1 [log-info: func[msg][sys/log/info 'HTTPD :msg]] + verbose >= 2 [log-more: func[msg][sys/log/more 'HTTPD :msg]] + verbose >= 3 [log-debug: func[msg][sys/log/debug 'HTTPD :msg]] + ] + system/options/log/httpd: verbose + ] + set-verbose 1 ] http-server: function [ - "Initialize simple HTTP server" + "Initialize simple HTTP server (DEPRECATED)" port [integer!] "Port to listen" /config "Possibility to change default settings" spec [block! object!] "Can hold: root, index, keep-alive, server-name" @@ -930,27 +988,58 @@ http-server: function [ actions [block! object!] "Functions like: On-Get On-Post On-Post-Received On-Read On-List-Dir On-Not-Found" /no-wait "Will not enter wait loop" ][ - server: open join httpd://: port - if config [ - if object? spec [ spec: body-of spec ] - if root: select spec 'root [ - spec/root: case [ - file? :root [attempt [dirize to-real-file clean-path root]] - 'current-dir = :root [what-dir] + sys/log/error 'HTTPD "`http-server` function is deprecated, use `start-http` instead!" + spec: either config [[]][to block! spec] + if actor [extend spec 'actor actions] + extend spec 'port port + start-http/:no-wait spec +] + +serve-http: function [ + "Initiate a HTTP server and handle HTTP requests" + spec [integer! file! block! object! map!] "Can hold: port, root, index, keep-alive, server-name, actor callbacks" + /no-wait "Will not enter wait loop" +][ + case [ + integer? port: spec [ + spec: reduce/no-set [port: spec root: what-dir] + ] + file? spec [ + root: dirize to-real-file clean-path spec + port: 8000 + spec: reduce/no-set [port: port root: root] + ] + 'else [ + unless block? spec [spec: body-of spec] + spec: reduce/no-set spec + port: any [select spec 'port 8000] ;; default port + root: select spec 'root + if string? root [root: to-rebol-file root] + if file? root [ + ;; to-real-file returns none when file does not exists on Posix + ;; that should be changed... also on Linux there is no trailing slash + ;; even when the source is a directory :-/ + spec/root: either exists? root [ + dirize to-real-file root + ][ + sys/log/error 'HTTPD ["Specified root not found:" as-red root] + none + ] ] ] - append server/extra/config spec ] - sys/log/info 'HTTPD ["Root directory: " as-green server/extra/config/root] - - ;unless system/options/quiet [? server/extra/config] - - if actor [ + server: open join httpd://: :port + sys/log/info 'HTTPD ["Listening on port:" :port "with root directory:" as-green spec/root] + + if actions: select spec 'actor [ append server/actor either block? actions [ + bind actions server/scheme reduce/no-set actions - ][ body-of actions ] + ][ bind body-of actions server/scheme ] + remove/part find spec 'actor 2 ;; not including actor in the config ] + append server/extra/config spec unless no-wait [ forever [ p: wait [server server/extra/subport 15] @@ -961,4 +1050,4 @@ http-server: function [ ] ] server -] \ No newline at end of file +] diff --git a/src/modules/spotify.reb b/src/modules/spotify.reb index ef60545786..c5f7b961c4 100644 --- a/src/modules/spotify.reb +++ b/src/modules/spotify.reb @@ -162,28 +162,28 @@ authorize: function [ ; Result from the server is returned as a redirect, so let's start simple server ; listening on specified port (limited to accept only local requests, as the redirect is ; going from the browser actually.. it automaticaly close itself once data are received - result: system/modules/httpd/http-server/config/actor ctx/port [ - root: #[false] ; we are not serving any content! - keep-alive: #[false] - ] [ - On-Accept: func [info [object!]][ - ; allow only connections from localhost - ; TRUE = accepted, FALSE = refuse - find [ 127.0.0.1 ] info/remote-ip - ] - On-Header: func [ctx [object!]][ - either ctx/inp/target/file == %/spotify-callback/ [ - ctx/out/status: 200 - ctx/out/content: ajoin [ - "

OAuth2 Spotify Callback

" - "
Request header:
" mold ctx/inp/header 
- "
Values:
" mold ctx/inp/target/values 
- "

You can close this window and return back to Rebol

" + result: serve-http [ + port: ctx/port + actor: [ + On-Accept: func [info [object!]][ + ; allow only connections from localhost + ; TRUE = accepted, FALSE = refuse + find [ 127.0.0.1 ] info/remote-ip + ] + On-Header: func [ctx [object!]][ + either ctx/inp/target/file == %/spotify-callback/ [ + ctx/out/status: 200 + ctx/out/content: ajoin [ + "

OAuth2 Spotify Callback

" + "
Request header:
" mold ctx/inp/header 
+ "
Values:
" mold ctx/inp/target/values 
+ "

You can close this window and return back to Rebol

" + ] + ctx/done?: ctx/inp/target/values + ][ + ctx/out/status: 405 + ctx/done?: true ] - ctx/done?: ctx/inp/target/values - ][ - ctx/out/status: 405 - ctx/done?: true ] ] ] diff --git a/src/tests/test-httpd.r3 b/src/tests/test-httpd.r3 index 4b374380be..54ac51dae2 100644 --- a/src/tests/test-httpd.r3 +++ b/src/tests/test-httpd.r3 @@ -1,9 +1,9 @@ Rebol [ Title: "Test HTTPD Scheme" - Date: 02-Jul-2020 + Date: 14-Dec-2023 Author: "Oldes" File: %test-httpd.r3 - Version: 0.6.0 + Version: 0.9.0 Note: { To test POST method from Rebol console, try this: ``` @@ -16,7 +16,7 @@ Rebol [ secure [%../modules/ allow] do %../modules/httpd.reb -system/options/log/httpd: 1 ; for verbose output +system/schemes/httpd/set-verbose 1 ; for verbose output system/options/quiet: false ; make sure that there is the directory for logs @@ -32,19 +32,17 @@ humans.txt: { \____________/~~~> http://github.com/oldes/ } -http-server/config/actor 8081 [ +serve-http [ + port: 8081 ;- Main server configuration - root: %httpd-root/ server-name: "nginx" ;= it's possible to hide real server name keep-alive: [30 100] ;= [timeout max-requests] or FALSE to turn it off log-access: %httpd-root/logs/test-access.log log-errors: %httpd-root/logs/test-errors.log list-dir?: #[true] - -] [ ;- Server's actor functions - + actor: [ On-Accept: func [info [object!]][ ; allow only connections from localhost ; TRUE = accepted, FALSE = refuse @@ -53,24 +51,7 @@ http-server/config/actor 8081 [ On-Header: func [ctx [object!] /local path key][ path: ctx/inp/target/file ;- detect some of common hacking attempts... - unless parse path [ - some [ - ;; common scripts, which we don't use - #"." [ - %php - | %aspx - | %cgi - ][end | #"?" | #"#"] reject - ; common hacking attempts to root folders... - | #"/" [ - %ecp/ ; we are not an exchange server - | %mifs/ ; either not MobileIron (https://stackoverflow.com/questions/67901776/what-does-the-line-mifs-services-logservice-mean) - | %GponForm/ ; nor Gpon router (https://www.vpnmentor.com/blog/critical-vulnerability-gpon-router/) - | %.env end ; https://stackoverflow.com/questions/64109005/do-these-env-get-requests-from-localhost-indicate-an-attack - ] reject - | 1 skip - ] - ][ + unless parse path anti-hacking-rules [ ctx/out/status: 418 ;= I'm a teapot ctx/out/header/Content-Type: "text/plain; charset=UTF-8" ctx/out/content: "Your silly hacking attempt was detected!" @@ -123,7 +104,7 @@ http-server/config/actor 8081 [ ] ] ] - On-Post-Received: func [ctx [object!]][ + On-Post: func [ctx [object!]][ ctx/out/content: ajoin [ "
Request header:
" mold ctx/inp/header 
"Received " ctx/inp/header/Content-Type/1 @@ -139,28 +120,7 @@ http-server/config/actor 8081 [ ? ctx/inp/content ] ] - On-Close-Websocket: func[ctx code /local reason][ - reason: any [ - select [ - 1000 "the purpose for which the connection was established has been fulfilled." - 1001 "a browser navigated away from a page." - 1002 "a protocol error." - 1003 "it has received a type of data it cannot accept." - 1007 "it has received data within a message that was not consistent with the type of the message." - 1008 "it has received a message that violates its policy." - 1009 "it has received a message that is too big for it to process." - 1010 "it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake." - 1011 "it encountered an unexpected condition that prevented it from fulfilling the request." - ] code - ajoin ["an unknown reason (" code ")"] - ] - print ["WS connection is closing because" reason] - unless empty? reason: ctx/inp/content [ - ;; optional client's reason - print ["Client's reason:" as-red to string! reason] - ] - ] - + ] ;end of actor ] From aa227fc7f8a5571ca3307255a93f0804a174c5b1 Mon Sep 17 00:00:00 2001 From: Oldes Date: Sun, 24 Dec 2023 13:08:42 +0100 Subject: [PATCH 24/60] FIX: avoid an error when loading an unset value --- src/mezz/sys-load.reb | 2 +- src/tests/units/load-test.r3 | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mezz/sys-load.reb b/src/mezz/sys-load.reb index 324bc461cd..69c269e255 100644 --- a/src/mezz/sys-load.reb +++ b/src/mezz/sys-load.reb @@ -354,7 +354,7 @@ load: function [ header empty? data 1 < length? data - ][data: first data] + ][set/any 'data first data] ] :data ] diff --git a/src/tests/units/load-test.r3 b/src/tests/units/load-test.r3 index c963388a89..bf51ac2e0b 100644 --- a/src/tests/units/load-test.r3 +++ b/src/tests/units/load-test.r3 @@ -103,6 +103,9 @@ Rebol [ e/near = "(line 4) 4line" ] + --test-- "loading an unset value" + --assert unset? try [load "#[unset]"] ;- no error + ===end-group=== ===start-group=== "find-script native" From 9715d1205bc45b0c195f4ab95f1cdd8c151abe43 Mon Sep 17 00:00:00 2001 From: Oldes Date: Sun, 24 Dec 2023 13:12:12 +0100 Subject: [PATCH 25/60] FIX: code simplified --- src/core/t-vector.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/t-vector.c b/src/core/t-vector.c index a0b40248f3..19c56f4fde 100644 --- a/src/core/t-vector.c +++ b/src/core/t-vector.c @@ -446,13 +446,7 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk) ser->tail = len; // !!! another way to do it? // Store info about the vector (could be moved to flags if necessary): - switch (bits) { - case 8: bits = 0; break; - case 16: bits = 1; break; - case 32: bits = 2; break; - case 64: bits = 3; break; - } - ser->size = (dims << 8) | (type << 3) | (sign << 2) | bits; + ser->size = (dims << 8) | (type << 3) | (sign << 2) | (bits >> 4); return ser; } From e402f9ea2a7e15e44a4bff769e51ca1fcc49de1f Mon Sep 17 00:00:00 2001 From: "Anthony M. Cook" Date: Wed, 27 Dec 2023 13:18:34 -0600 Subject: [PATCH 26/60] Document FORMAT-DATE-TIME --- src/mezz/mezz-series.reb | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mezz/mezz-series.reb b/src/mezz/mezz-series.reb index 22aead22cb..21b1e801d2 100644 --- a/src/mezz/mezz-series.reb +++ b/src/mezz/mezz-series.reb @@ -489,6 +489,7 @@ format: function [ ] format-date-time: function/with [ + "replaces a subset of ISO 8601 abbreviations such as yyyy-MM-dd hh:mm:ss" value [date! time!] rule [string! tag!] ][ From 3ad3287b9c1369a8434536df335127857e5bc873 Mon Sep 17 00:00:00 2001 From: "Anthony M. Cook" Date: Wed, 27 Dec 2023 17:29:20 -0600 Subject: [PATCH 27/60] Minor readme cleanup Fixes a typo and updates the grammar --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 35baa17351..9679918b21 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,13 @@ # Rebol [R3] Source Code Distribution -Purpose of this **Rebol fork** is to push the origial [Carl's source](https://github.com/rebol/rebol) to be usable at least like Rebol 2, -but keep the source code clean and project easy to build. Use [CHANGES.md](https://github.com/Oldes/Rebol3/blob/master/CHANGES.md) file to see changes made in this branch. +Purpose of this **Rebol fork** is to push [Carl's original source](https://github.com/rebol/rebol) to be at least as usable as Rebol 2 while keeping the source code clean and project easy to build. Use [CHANGES.md](https://github.com/Oldes/Rebol3/blob/master/CHANGES.md) file to see changes made in this branch. -### Issues reporting +### Issue Reporting -Preferred way for issue reporting is using [dedicated issue repository](https://github.com/Oldes/Rebol-issues/issues). It's a fork of the original Rebol issue repository, which was filled with issues from [CureCode issue tracker](https://www.curecode.org/rebol3/view-tickets.rsp), which was used before Rebol was on Github. I'm not using the original Rebol issue repository, because I was not allowed to even add labels to my own issues. It was later moved under Metaeducation account and is used for Ren-C development anyway. +Preferred way to report issues is using the [dedicated issue repository](https://github.com/Oldes/Rebol-issues/issues). It's a fork of the original Rebol issue repository, which was filled with issues from the [CureCode issue tracker](https://www.curecode.org/rebol3/view-tickets.rsp), which was used before Rebol was on Github. I'm not using the original Rebol issue repository, because I was not allowed to even add labels to my own issues. It was later moved under Metaeducation account and is used for Ren-C development anyway. -### Precompiled binaries +### Precompiled Binaries There are available precompiled binaries for each [release](https://github.com/Oldes/Rebol3/releases). So far there are 3 main build types: 1. **Base** is a build with minimal additions (not much useful) From 9bb91086c266e190121c075b0b412c29e9c06651 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 4 Jan 2024 15:11:20 +0100 Subject: [PATCH 28/60] CHANGE: Zlib source updated to version 1.3.0.1 --- make/tools/make-zlib.r3 | 407 ------- src/core/u-zlib.c | 2508 +++++++++++++++++---------------------- src/include/sys-zlib.h | 466 ++++---- 3 files changed, 1321 insertions(+), 2060 deletions(-) delete mode 100644 make/tools/make-zlib.r3 diff --git a/make/tools/make-zlib.r3 b/make/tools/make-zlib.r3 deleted file mode 100644 index 8bf13a0140..0000000000 --- a/make/tools/make-zlib.r3 +++ /dev/null @@ -1,407 +0,0 @@ -REBOL [ - System: "REBOL [R3] Language Interpreter and Run-time Environment" - Title: "Make sys-zlib.h and u-zlib.c" - Rights: { - Copyright 2012-2022 Ren-C Open Source Contributors - REBOL is a trademark of REBOL Technologies - } - License: { - Licensed under the Apache License, Version 2.0 - See: http://www.apache.org/licenses/LICENSE-2.0 - } - Purpose: { - In order to limit build dependencies, Rebol makes a snapshot of a - subset of certain libraries to include in the source distribution. - This script will extract just the parts of ZLIB that Rebol needs - to put into one .h file and one .c file. It generates its - snapshot from their official source repository: - - https://github.com/madler/zlib - - Any significant reorganization of the ZLIB codebase would require - updating this script accordingly. It was last tested on 1.2.11 - (released 15-Jan-2017) - } - Note: { - "This runs relative to ../tools directory." - - !!! TBD: The `register` keyword has been deprecated. If zlib doesn't - remove it itself, then on the next import the by-hand removals will - have to be repeated -or- this script will need to be updated to get - rid of them (note `register` is used in comments too): - - https://stackoverflow.com/a/30809775 - } - Author: [] -] - -do %c-lexicals.reb - -; -; Target paths+filenames for the generated include and source file -; -path-include: %../../src/include/ -file-include: %sys-zlib.h -path-source: %../../src/core/ -file-source: %u-zlib.c - -_: #[none] - -path-zlib: %/b\tree\utility\zlib\ ;https://raw.githubusercontent.com/madler/zlib/master/ - -; -; Disable #include "foo.h" style inclusions (but not #include style) -; Optionally will inline a list of files at the inclusion point -; -disable-user-includes: function [ - lines [block!] {Block of strings} - /inline files [block!] {Block of filenames to inline if seen} - /stdio {Disable stdio.h} -] [ - open-include: charset {"<} - close-include: charset {">} - - include-rule: compose [ - ((if stdio [ - [open-include copy name "stdio.h" close-include |] - ])) - {"} copy name to {"} - ] - - forall lines [ - if parse line: lines/1 [ - any space {#} - any space {include} - some space include-rule to end - ][ - either pos: find files (as file! name) [ - change/part lines (read/lines path-zlib/:name) 1 - take pos - ][ - insert line ajoin [{//} space] - append line ajoin [ - space {/* REBOL: see make-zlib.r */} - ] - ] - ] - ] - - if all [inline not empty? files] [ - print as-red [ - {Not all headers inlined by make-zlib:} (mold headers) LF - {If we inline a header, should happen once and only once for each} - ] - halt - ] -] - -; -; Stern warning not to edit the files -; - -make-warning-lines: func [name [file!] title [string!]] [ - reduce [ - {//} - {// Extraction of ZLIB compression and decompression routines} - {// for REBOL [R3] Language Interpreter and Run-time Environment} - {// This is a code-generated file.} - {//} - {// ZLIB Copyright notice:} - {//} - {// (C) 1995-2022 Jean-loup Gailly and Mark Adler} - {//} - {// This software is provided 'as-is', without any express or implied} - {// warranty. In no event will the authors be held liable for any damages} - {// arising from the use of this software.} - {//} - {// Permission is granted to anyone to use this software for any purpose,} - {// including commercial applications, and to alter it and redistribute it} - {// freely, subject to the following restrictions:} - {//} - {// 1. The origin of this software must not be misrepresented; you must not} - {// claim that you wrote the original software. If you use this software} - {// in a product, an acknowledgment in the product documentation would be} - {// appreciated but is not required.} - {// 2. Altered source versions must be plainly marked as such, and must not be} - {// misrepresented as being the original software.} - {// 3. This notice may not be removed or altered from any source distribution.} - {//} - {// Jean-loup Gailly Mark Adler} - {// jloup@gzip.org madler@alumni.caltech.edu} - {//} - {// REBOL is a trademark of REBOL Technologies} - {// Licensed under the Apache License, Version 2.0} - {//} - {// **********************************************************************} - {//} - ajoin [{// Title: } title] - ajoin [{// Date: } now/date] - ajoin [{// File: } name] - {//} - {// AUTO-GENERATED FILE - Do not modify. (From: make-zlib.r)} - {//} - ] -] - -fix-kr: function [ - "Fix K&R style C function definition" - source -][ - single-param: bind [ - identifier ;(part of)type - some [ - any white-space - any [#"*" any white-space] - - ; It could get here even after last identifier, so this tmp-start - ; is not the begining of the name, but the last one is... - ; - tmp-start: copy name: - identifier ( - name-start: tmp-start - ) - any white-space - any [#"*" any white-space] - ] - ] c-lexical/grammar - - parse source bind [ - while [ - copy fn: identifier - any white-space - #"(" open-paren: to #")" close-paren: #")" - param-ser: copy param-spec: [ - some [ - some [any white-space any [#"*" any white-space] - identifier any white-space opt #"," - any [#"*" any white-space] - ] #";" - ] - any white-space - ] - #"^{" check-point: ( - ;print ["func:" to string! fn] - remove/part param-ser length? param-spec - insert param-ser "^/" - length-diff: 1 - (length? param-spec) - - param-len: (index? close-paren) - (index? open-paren) - params: copy/part open-paren param-len - remove/part open-paren param-len - length-diff: length-diff - param-len - - - param-block: make block! 8 - parse params [ - any white-space - copy name: identifier ( - append param-block reduce [name _] - ) - any [ - any white-space - #"," - any white-space - copy name: identifier ( - append param-block reduce [name _] - ) - ] - end - ] - - ;dump param-block - - ; a param spec could be in the form of: - ; 1) "int i;" or - ; 2) "int i, *j, **k;" - ;dump param-spec - parse param-spec [ - any white-space - some [ - (typed?: true) - single-param-start: single-param ( - spec-type: ( - copy/part single-param-start - (index? name-start) - - (index? single-param-start) - ) - ;dump spec-type - ) - any [ - any white-space - param-end: #"," ( - ; case 2) - ; spec-type should be "int " - ; name should be "i" - poke (find/skip param-block name 2) 2 - either typed? [ - (copy/part single-param-start - (index? param-end) - - (index? single-param-start) - ) - ][ - ; handling "j" in case 2) - ajoin [ - spec-type ; "int " - (copy/part single-param-start - (index? param-end) - - (index? single-param-start) - ) ; " *j" - ] - ] - typed?: false - ) - single-param-start: - any white-space - any [#"*" any white-space] - copy name identifier - ] - any white-space - param-end: #";" - ( - poke (find/skip param-block name 2) 2 - either typed? [ - (copy/part single-param-start - (index? param-end) - - (index? single-param-start) - ) - ][ - ; handling "k" in case 2) - ajoin [ - spec-type ; "int " - (copy/part single-param-start - (index? param-end) - - (index? single-param-start) - ) ; " **k" - ] - ] - ) - any white-space - ] - ] - - insert open-paren new-param: combine/with ( - extract/index param-block 2 2 - ) ",^/ " - insert open-paren "^/ " - - length-diff: length-diff + length? new-param - - check-point: skip check-point length-diff - ) - :check-point - | skip - ] - end - ] c-lexical/grammar - - source -] - -fix-const-char: func [ - source -][ - parse source bind [ - while [ - "strm" any white-space "->" any white-space - "msg" any white-space "=" any white-space - "(" any white-space change "char" "z_const char" - any white-space "*" any white-space ")" - | skip - ] - end - ] c-lexical/grammar - source -] - -;do %common.r - -; -; Generate %sys-zlib.h Aggregate Header File -; - -header-lines: copy [] - -foreach h-file [ - %zconf.h - %zutil.h - %zlib.h - %deflate.h -] [ - append header-lines read/lines path-zlib/:h-file -] - -disable-user-includes header-lines - -insert header-lines [ - {} - {// Rebol} - {#define NO_DUMMY_DECL 1} - {#define Z_PREFIX 1} - {#define ZLIB_CONST} - {// **********************************************************************} - {} -] - -insert header-lines make-warning-lines file-include {ZLIB aggregated header} - -write/lines path-include/:file-include header-lines - - - -; -; Generate %u-zlib.c Aggregate Source File -; - -source-lines: copy [] - -append source-lines read/lines path-zlib/crc32.c - -; -; Macros DO1 and DO8 are defined differently in crc32.c, and if you don't -; #undef them you'll get a redefinition warning. -; -append source-lines [ - {#undef DO1 /* REBOL: see make-zlib.r */} - {#undef DO8 /* REBOL: see make-zlib.r */} -] - -foreach c-file [ - %adler32.c - - %deflate.c - %zutil.c - %compress.c - %uncompr.c - %trees.c - - %inftrees.h - %inftrees.c - %inffast.h - %inflate.h - %inffast.c - %inflate.c -][ - append source-lines read/lines path-zlib/:c-file -] - -disable-user-includes/stdio/inline source-lines copy [ - %trees.h - %inffixed.h - %crc32.h -] - -insert source-lines [ - {} - {#include "sys-zlib.h" /* REBOL: see make-zlib.r */} - {#define local static} - {} -] - -insert source-lines make-warning-lines file-source {ZLIB aggregated source} - -;all-source: make string! 200'000 -;forall source-lines [append append all-source source-lines/1 LF] -;;write rejoin [path-source file-source] fix-const-char fix-kr all-source -;write path-source/:file-source fix-const-char all-source - -write/lines path-source/:file-source source-lines diff --git a/src/core/u-zlib.c b/src/core/u-zlib.c index 7c9cd7a3d7..2d9e77faae 100644 --- a/src/core/u-zlib.c +++ b/src/core/u-zlib.c @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////// // File: u-zlib.c // Home: https://github.com/Siskin-framework/Rebol-Zlib -// Date: 25-Jan-2023 +// Date: 4-Jan-2024 // Note: This file is amalgamated from these sources: // // crc32.c @@ -130,19 +130,6 @@ # define ARMCRC32 #endif -/* Local functions. */ -local z_crc_t multmodp OF((z_crc_t a, z_crc_t b)); -local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); - -#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) - local z_word_t byte_swap OF((z_word_t word)); -#endif - -#if defined(W) && !defined(ARMCRC32) - local z_crc_t crc_word OF((z_word_t data)); - local z_word_t crc_word_big OF((z_word_t data)); -#endif - #if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE)) /* Swap the bytes in a z_word_t to convert between little and big endian. Any @@ -150,9 +137,7 @@ local z_crc_t x2nmodp OF((z_off64_t n, unsigned k)); instruction, if one is available. This assumes that word_t is either 32 bits or 64 bits. */ -local z_word_t byte_swap(word) - z_word_t word; -{ +local z_word_t byte_swap(z_word_t word) { # if W == 8 return (word & 0xff00000000000000) >> 56 | @@ -173,458 +158,79 @@ local z_word_t byte_swap(word) } #endif -/* CRC polynomial. */ -#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ - #ifdef DYNAMIC_CRC_TABLE - -local z_crc_t FAR crc_table[256]; -local z_crc_t FAR x2n_table[32]; -local void make_crc_table OF((void)); -#ifdef W - local z_word_t FAR crc_big_table[256]; - local z_crc_t FAR crc_braid_table[W][256]; - local z_word_t FAR crc_braid_big_table[W][256]; - local void braid OF((z_crc_t [][256], z_word_t [][256], int, int)); -#endif -#ifdef MAKECRCH - local void write_table OF((FILE *, const z_crc_t FAR *, int)); - local void write_table32hi OF((FILE *, const z_word_t FAR *, int)); - local void write_table64 OF((FILE *, const z_word_t FAR *, int)); -#endif /* MAKECRCH */ - -/* - Define a once() function depending on the availability of atomics. If this is - compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in - multiple threads, and if atomics are not available, then get_crc_table() must - be called to initialize the tables and must return before any threads are - allowed to compute or combine CRCs. +/* ========================================================================= + * Table of powers of x for combining CRC-32s, filled in by make_crc_table() + * below. */ - -/* Definition of once functionality. */ -typedef struct once_s once_t; -local void once OF((once_t *, void (*)(void))); - -/* Check for the availability of atomics. */ -#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ - !defined(__STDC_NO_ATOMICS__) - -#include - -/* Structure for once(), which must be initialized with ONCE_INIT. */ -struct once_s { - atomic_flag begun; - atomic_int done; -}; -#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} - -/* - Run the provided init() function exactly once, even if multiple threads - invoke once() at the same time. The state must be a once_t initialized with - ONCE_INIT. + local z_crc_t FAR x2n_table[32]; +#else +/* ========================================================================= + * Tables for byte-wise and braided CRC-32 calculations, and a table of powers + * of x for combining CRC-32s, all made by make_crc_table(). */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ - if (!atomic_load(&state->done)) { - if (atomic_flag_test_and_set(&state->begun)) - while (!atomic_load(&state->done)) - ; - else { - init(); - atomic_store(&state->done, 1); - } - } -} - -#else /* no atomics */ - -/* Structure for once(), which must be initialized with ONCE_INIT. */ -struct once_s { - volatile int begun; - volatile int done; -}; -#define ONCE_INIT {0, 0} - -/* Test and set. Alas, not atomic, but tries to minimize the period of - vulnerability. */ -local int test_and_set OF((int volatile *)); -local int test_and_set(flag) - int volatile *flag; -{ - int was; - - was = *flag; - *flag = 1; - return was; -} - -/* Run the provided init() function once. This is not thread-safe. */ -local void once(state, init) - once_t *state; - void (*init)(void); -{ - if (!state->done) { - if (test_and_set(&state->begun)) - while (!state->done) - ; - else { - init(); - state->done = 1; - } - } -} - -#endif - -/* State for once(). */ -local once_t made = ONCE_INIT; - -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x - (which is shifting right by one and adding x^32 mod p if the bit shifted out - is a one). We start with the highest power (least significant bit) of q and - repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all the - information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. +//REBOL: # include "crc32.h" +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c */ -local void make_crc_table() -{ - unsigned i, j, n; - z_crc_t p; - - /* initialize the CRC of bytes tables */ - for (i = 0; i < 256; i++) { - p = i; - for (j = 0; j < 8; j++) - p = p & 1 ? (p >> 1) ^ POLY : p >> 1; - crc_table[i] = p; -#ifdef W - crc_big_table[i] = byte_swap(p); -#endif - } - - /* initialize the x^2^n mod p(x) table */ - p = (z_crc_t)1 << 30; /* x^1 */ - x2n_table[0] = p; - for (n = 1; n < 32; n++) - x2n_table[n] = p = multmodp(p, p); +local const z_crc_t FAR crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; #ifdef W - /* initialize the braiding tables -- needs x2n_table[] */ - braid(crc_braid_table, crc_braid_big_table, N, W); -#endif - -#ifdef MAKECRCH - { - /* - The crc32.h header file contains tables for both 32-bit and 64-bit - z_word_t's, and so requires a 64-bit type be available. In that case, - z_word_t must be defined to be 64-bits. This code then also generates - and writes out the tables for the case that z_word_t is 32 bits. - */ -#if !defined(W) || W != 8 -# error Need a 64-bit integer type in order to generate crc32.h. -#endif - FILE *out; - int k, n; - z_crc_t ltl[8][256]; - z_word_t big[8][256]; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - - /* write out little-endian CRC table to crc32.h */ - fprintf(out, - "/* crc32.h -- tables for rapid CRC calculation\n" - " * Generated automatically by crc32.c\n */\n" - "\n" - "local const z_crc_t FAR crc_table[] = {\n" - " "); - write_table(out, crc_table, 256); - fprintf(out, - "};\n"); - /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#ifdef W\n" - "\n" - "#if W == 8\n" - "\n" - "local const z_word_t FAR crc_big_table[] = {\n" - " "); - write_table64(out, crc_big_table, 256); - fprintf(out, - "};\n"); - - /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#else /* W == 4 */\n" - "\n" - "local const z_word_t FAR crc_big_table[] = {\n" - " "); - write_table32hi(out, crc_big_table, 256); - fprintf(out, - "};\n" - "\n" - "#endif\n"); - - /* write out braid tables for each value of N */ - for (n = 1; n <= 6; n++) { - fprintf(out, - "\n" - "#if N == %d\n", n); - - /* compute braid tables for this N and 64-bit word_t */ - braid(ltl, big, n, 8); - - /* write out braid tables for 64-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#if W == 8\n" - "\n" - "local const z_crc_t FAR crc_braid_table[][256] = {\n"); - for (k = 0; k < 8; k++) { - fprintf(out, " {"); - write_table(out, ltl[k], 256); - fprintf(out, "}%s", k < 7 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); - for (k = 0; k < 8; k++) { - fprintf(out, " {"); - write_table64(out, big[k], 256); - fprintf(out, "}%s", k < 7 ? ",\n" : ""); - } - fprintf(out, - "};\n"); - - /* compute braid tables for this N and 32-bit word_t */ - braid(ltl, big, n, 4); - - /* write out braid tables for 32-bit z_word_t to crc32.h */ - fprintf(out, - "\n" - "#else /* W == 4 */\n" - "\n" - "local const z_crc_t FAR crc_braid_table[][256] = {\n"); - for (k = 0; k < 4; k++) { - fprintf(out, " {"); - write_table(out, ltl[k], 256); - fprintf(out, "}%s", k < 3 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); - for (k = 0; k < 4; k++) { - fprintf(out, " {"); - write_table32hi(out, big[k], 256); - fprintf(out, "}%s", k < 3 ? ",\n" : ""); - } - fprintf(out, - "};\n" - "\n" - "#endif\n" - "\n" - "#endif\n"); - } - fprintf(out, - "\n" - "#endif\n"); - - /* write out zeros operator table to crc32.h */ - fprintf(out, - "\n" - "local const z_crc_t FAR x2n_table[] = {\n" - " "); - write_table(out, x2n_table, 32); - fprintf(out, - "};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH - -/* - Write the 32-bit values in table[0..k-1] to out, five per line in - hexadecimal separated by commas. - */ -local void write_table(out, table, k) - FILE *out; - const z_crc_t FAR *table; - int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", - (unsigned long)(table[n]), - n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); -} - -/* - Write the high 32-bits of each value in table[0..k-1] to out, five per line - in hexadecimal separated by commas. - */ -local void write_table32hi(out, table, k) -FILE *out; -const z_word_t FAR *table; -int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", - (unsigned long)(table[n] >> 32), - n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); -} - -/* - Write the 64-bit values in table[0..k-1] to out, three per line in - hexadecimal separated by commas. This assumes that if there is a 64-bit - type, then there is also a long long integer type, and it is at least 64 - bits. If not, then the type cast and format string can be adjusted - accordingly. - */ -local void write_table64(out, table, k) - FILE *out; - const z_word_t FAR *table; - int k; -{ - int n; - - for (n = 0; n < k; n++) - fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", - (unsigned long long)(table[n]), - n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); -} - -/* Actually do the deed. */ -int main() -{ - make_crc_table(); - return 0; -} - -#endif /* MAKECRCH */ - -#ifdef W -/* - Generate the little and big-endian braid tables for the given n and z_word_t - size w. Each array must have room for w blocks of 256 elements. - */ -local void braid(ltl, big, n, w) - z_crc_t ltl[][256]; - z_word_t big[][256]; - int n; - int w; -{ - int k; - z_crc_t i, p, q; - for (k = 0; k < w; k++) { - p = x2nmodp((n * w + 3 - k) << 3, 0); - ltl[k][0] = 0; - big[w - 1 - k][0] = 0; - for (i = 1; i < 256; i++) { - ltl[k][i] = q = multmodp(i << 24, p); - big[w - 1 - k][i] = byte_swap(q); - } - } -} -#endif - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables for byte-wise and braided CRC-32 calculations, and a table of powers - * of x for combining CRC-32s, all made by make_crc_table(). - */ -//REBOL: #include "crc32.h" -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const z_crc_t FAR crc_table[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d}; - -#ifdef W - -#if W == 8 +#if W == 8 local const z_word_t FAR crc_big_table[] = { 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, @@ -10011,63 +9617,410 @@ local const z_crc_t FAR x2n_table[] = { 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, 0xc40ba6d0, 0xc4e22c3c}; -#endif /* DYNAMIC_CRC_TABLE */ +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ + +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +local z_crc_t multmodp(z_crc_t a, z_crc_t b) { + z_crc_t m, p; + + m = (z_crc_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. + */ +local z_crc_t x2nmodp(z_off64_t n, unsigned k) { + z_crc_t p; + + p = (z_crc_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +#ifdef DYNAMIC_CRC_TABLE +/* ========================================================================= + * Build the tables for byte-wise and braided CRC-32 calculations, and a table + * of powers of x for combining CRC-32s. + */ +local z_crc_t FAR crc_table[256]; +#ifdef W + local z_word_t FAR crc_big_table[256]; + local z_crc_t FAR crc_braid_table[W][256]; + local z_word_t FAR crc_braid_big_table[W][256]; + local void braid(z_crc_t [][256], z_word_t [][256], int, int); +#endif +#ifdef MAKECRCH + local void write_table(FILE *, const z_crc_t FAR *, int); + local void write_table32hi(FILE *, const z_word_t FAR *, int); + local void write_table64(FILE *, const z_word_t FAR *, int); +#endif /* MAKECRCH */ + +/* + Define a once() function depending on the availability of atomics. If this is + compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in + multiple threads, and if atomics are not available, then get_crc_table() must + be called to initialize the tables and must return before any threads are + allowed to compute or combine CRCs. + */ + +/* Definition of once functionality. */ +typedef struct once_s once_t; + +/* Check for the availability of atomics. */ +#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \ + !defined(__STDC_NO_ATOMICS__) + +#include + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + atomic_flag begun; + atomic_int done; +}; +#define ONCE_INIT {ATOMIC_FLAG_INIT, 0} + +/* + Run the provided init() function exactly once, even if multiple threads + invoke once() at the same time. The state must be a once_t initialized with + ONCE_INIT. + */ +local void once(once_t *state, void (*init)(void)) { + if (!atomic_load(&state->done)) { + if (atomic_flag_test_and_set(&state->begun)) + while (!atomic_load(&state->done)) + ; + else { + init(); + atomic_store(&state->done, 1); + } + } +} + +#else /* no atomics */ + +/* Structure for once(), which must be initialized with ONCE_INIT. */ +struct once_s { + volatile int begun; + volatile int done; +}; +#define ONCE_INIT {0, 0} + +/* Test and set. Alas, not atomic, but tries to minimize the period of + vulnerability. */ +local int test_and_set(int volatile *flag) { + int was; + + was = *flag; + *flag = 1; + return was; +} + +/* Run the provided init() function once. This is not thread-safe. */ +local void once(once_t *state, void (*init)(void)) { + if (!state->done) { + if (test_and_set(&state->begun)) + while (!state->done) + ; + else { + init(); + state->done = 1; + } + } +} + +#endif + +/* State for once(). */ +local once_t made = ONCE_INIT; + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x + (which is shifting right by one and adding x^32 mod p if the bit shifted out + is a one). We start with the highest power (least significant bit) of q and + repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all the + information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. + */ + +local void make_crc_table(void) { + unsigned i, j, n; + z_crc_t p; + + /* initialize the CRC of bytes tables */ + for (i = 0; i < 256; i++) { + p = i; + for (j = 0; j < 8; j++) + p = p & 1 ? (p >> 1) ^ POLY : p >> 1; + crc_table[i] = p; +#ifdef W + crc_big_table[i] = byte_swap(p); +#endif + } + + /* initialize the x^2^n mod p(x) table */ + p = (z_crc_t)1 << 30; /* x^1 */ + x2n_table[0] = p; + for (n = 1; n < 32; n++) + x2n_table[n] = p = multmodp(p, p); + +#ifdef W + /* initialize the braiding tables -- needs x2n_table[] */ + braid(crc_braid_table, crc_braid_big_table, N, W); +#endif + +#ifdef MAKECRCH + { + /* + The crc32.h header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. + */ +#if !defined(W) || W != 8 +# error Need a 64-bit integer type in order to generate crc32.h. +#endif + FILE *out; + int k, n; + z_crc_t ltl[8][256]; + z_word_t big[8][256]; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + + /* write out little-endian CRC table to crc32.h */ + fprintf(out, + "/* crc32.h -- tables for rapid CRC calculation\n" + " * Generated automatically by crc32.c\n */\n" + "\n" + "local const z_crc_t FAR crc_table[] = {\n" + " "); + write_table(out, crc_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#ifdef W\n" + "\n" + "#if W == 8\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table64(out, crc_big_table, 256); + fprintf(out, + "};\n"); + + /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_word_t FAR crc_big_table[] = {\n" + " "); + write_table32hi(out, crc_big_table, 256); + fprintf(out, + "};\n" + "\n" + "#endif\n"); + + /* write out braid tables for each value of N */ + for (n = 1; n <= 6; n++) { + fprintf(out, + "\n" + "#if N == %d\n", n); + + /* compute braid tables for this N and 64-bit word_t */ + braid(ltl, big, n, 8); + + /* write out braid tables for 64-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#if W == 8\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + fprintf(out, " {"); + write_table64(out, big[k], 256); + fprintf(out, "}%s", k < 7 ? ",\n" : ""); + } + fprintf(out, + "};\n"); + + /* compute braid tables for this N and 32-bit word_t */ + braid(ltl, big, n, 4); + + /* write out braid tables for 32-bit z_word_t to crc32.h */ + fprintf(out, + "\n" + "#else /* W == 4 */\n" + "\n" + "local const z_crc_t FAR crc_braid_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table(out, ltl[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "local const z_word_t FAR crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + fprintf(out, " {"); + write_table32hi(out, big[k], 256); + fprintf(out, "}%s", k < 3 ? ",\n" : ""); + } + fprintf(out, + "};\n" + "\n" + "#endif\n" + "\n" + "#endif\n"); + } + fprintf(out, + "\n" + "#endif\n"); + + /* write out zeros operator table to crc32.h */ + fprintf(out, + "\n" + "local const z_crc_t FAR x2n_table[] = {\n" + " "); + write_table(out, x2n_table, 32); + fprintf(out, + "};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH + +/* + Write the 32-bit values in table[0..k-1] to out, five per line in + hexadecimal separated by commas. + */ +local void write_table(FILE *out, const z_crc_t FAR *table, int k) { + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the high 32-bits of each value in table[0..k-1] to out, five per line + in hexadecimal separated by commas. + */ +local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) { + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ", + (unsigned long)(table[n] >> 32), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} + +/* + Write the 64-bit values in table[0..k-1] to out, three per line in + hexadecimal separated by commas. This assumes that if there is a 64-bit + type, then there is also a long long integer type, and it is at least 64 + bits. If not, then the type cast and format string can be adjusted + accordingly. + */ +local void write_table64(FILE *out, const z_word_t FAR *table, int k) { + int n; + + for (n = 0; n < k; n++) + fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ", + (unsigned long long)(table[n]), + n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); +} + +/* Actually do the deed. */ +int main(void) { + make_crc_table(); + return 0; +} -/* ======================================================================== - * Routines used for CRC calculation. Some are also required for the table - * generation above. - */ +#endif /* MAKECRCH */ +#ifdef W /* - Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, - reflected. For speed, this requires that a not be zero. + Generate the little and big-endian braid tables for the given n and z_word_t + size w. Each array must have room for w blocks of 256 elements. */ -local z_crc_t multmodp(a, b) - z_crc_t a; - z_crc_t b; -{ - z_crc_t m, p; - - m = (z_crc_t)1 << 31; - p = 0; - for (;;) { - if (a & m) { - p ^= b; - if ((a & (m - 1)) == 0) - break; +local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) { + int k; + z_crc_t i, p, q; + for (k = 0; k < w; k++) { + p = x2nmodp((n * w + 3 - k) << 3, 0); + ltl[k][0] = 0; + big[w - 1 - k][0] = 0; + for (i = 1; i < 256; i++) { + ltl[k][i] = q = multmodp(i << 24, p); + big[w - 1 - k][i] = byte_swap(q); } - m >>= 1; - b = b & 1 ? (b >> 1) ^ POLY : b >> 1; } - return p; } +#endif -/* - Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been - initialized. - */ -local z_crc_t x2nmodp(n, k) - z_off64_t n; - unsigned k; -{ - z_crc_t p; - - p = (z_crc_t)1 << 31; /* x^0 == 1 */ - while (n) { - if (n & 1) - p = multmodp(x2n_table[k & 31], p); - n >>= 1; - k++; - } - return p; -} +#endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32(), and to force the * generation of the CRC tables in a threaded application. */ -const z_crc_t FAR * ZEXPORT get_crc_table() -{ +const z_crc_t FAR * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -10093,11 +10046,8 @@ const z_crc_t FAR * ZEXPORT get_crc_table() #define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */ #define Z_BATCH_MIN 800 /* fewest words in a final batch */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ +unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, + z_size_t len) { z_crc_t val; z_word_t crc1, crc2; const z_word_t *word; @@ -10197,18 +10147,14 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) least-significant byte of the word as the first byte of data, without any pre or post conditioning. This is used to combine the CRCs of each braid. */ -local z_crc_t crc_word(data) - z_word_t data; -{ +local z_crc_t crc_word(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data >> 8) ^ crc_table[data & 0xff]; return (z_crc_t)data; } -local z_word_t crc_word_big(data) - z_word_t data; -{ +local z_word_t crc_word_big(z_word_t data) { int k; for (k = 0; k < W; k++) data = (data << 8) ^ @@ -10219,11 +10165,8 @@ local z_word_t crc_word_big(data) #endif /* ========================================================================= */ -unsigned long ZEXPORT crc32_z(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - z_size_t len; -{ +unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, + z_size_t len) { /* Return initial CRC, if requested. */ if (buf == Z_NULL) return 0; @@ -10255,8 +10198,8 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) words = (z_word_t const *)buf; /* Do endian check at execution time instead of compile time, since ARM - processors can change the endianess at execution time. If the - compiler knows what the endianess will be, it can optimize out the + processors can change the endianness at execution time. If the + compiler knows what the endianness will be, it can optimize out the check and the unused branch. */ endian = 1; if (*(unsigned char *)&endian) { @@ -10543,20 +10486,13 @@ unsigned long ZEXPORT crc32_z(crc, buf, len) #endif /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - uInt len; -{ +unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, + uInt len) { return crc32_z(crc, buf, len); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine64(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off64_t len2; -{ +uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -10564,18 +10500,12 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2) } /* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ +uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { return crc32_combine64(crc1, crc2, (z_off64_t)len2); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen64(len2) - z_off64_t len2; -{ +uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) { #ifdef DYNAMIC_CRC_TABLE once(&made, make_crc_table); #endif /* DYNAMIC_CRC_TABLE */ @@ -10583,18 +10513,12 @@ uLong ZEXPORT crc32_combine_gen64(len2) } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_gen(len2) - z_off_t len2; -{ +uLong ZEXPORT crc32_combine_gen(z_off_t len2) { return crc32_combine_gen64((z_off64_t)len2); } /* ========================================================================= */ -uLong ZEXPORT crc32_combine_op(crc1, crc2, op) - uLong crc1; - uLong crc2; - uLong op; -{ +uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) { return multmodp(op, crc1) ^ (crc2 & 0xffffffff); } /* adler32.c -- compute the Adler-32 checksum of a data stream @@ -10606,8 +10530,6 @@ uLong ZEXPORT crc32_combine_op(crc1, crc2, op) //REBOL: #include "zutil.h" -local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); - #define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -10659,11 +10581,7 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #endif /* ========================================================================= */ -uLong ZEXPORT adler32_z(adler, buf, len) - uLong adler; - const Bytef *buf; - z_size_t len; -{ +uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) { unsigned long sum2; unsigned n; @@ -10730,20 +10648,12 @@ uLong ZEXPORT adler32_z(adler, buf, len) } /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ +uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { return adler32_z(adler, buf, len); } /* ========================================================================= */ -local uLong adler32_combine_(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; @@ -10768,23 +10678,15 @@ local uLong adler32_combine_(adler1, adler2, len2) } /* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ +uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } -uLong ZEXPORT adler32_combine64(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off64_t len2; -{ +uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -10837,7 +10739,7 @@ uLong ZEXPORT adler32_combine64(adler1, adler2, len2) //REBOL: #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; + " deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -10845,9 +10747,6 @@ const char deflate_copyright[] = copyright string in the executable of your product. */ -/* =========================================================================== - * Function prototypes. - */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ @@ -10855,29 +10754,16 @@ typedef enum { finish_done /* finish done, accept no more input or output */ } block_state; -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ -local int deflateStateCheck OF((z_streamp strm)); -local void slide_hash OF((deflate_state *s)); -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_stored(deflate_state *s, int flush); +local block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local block_state deflate_rle OF((deflate_state *s, int flush)); -local block_state deflate_huff OF((deflate_state *s, int flush)); -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -local uInt longest_match OF((deflate_state *s, IPos cur_match)); - -#ifdef ZLIB_DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); +local block_state deflate_slow(deflate_state *s, int flush); #endif +local block_state deflate_rle(deflate_state *s, int flush); +local block_state deflate_huff(deflate_state *s, int flush); /* =========================================================================== * Local data @@ -10980,9 +10866,12 @@ local const config configuration_table[10] = { * bit values at the expense of memory usage). We slide even when level == 0 to * keep the hash table consistent if we switch back to level > 0 later. */ -local void slide_hash(s) - deflate_state *s; -{ +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) + __attribute__((no_sanitize("memory"))) +# endif +#endif +local void slide_hash(deflate_state *s) { unsigned n, m; Posf *p; uInt wsize = s->w_size; @@ -11006,30 +10895,177 @@ local void slide_hash(s) #endif } +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) { + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(deflate_state *s) { + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize + MAX_DIST(s)) { + + zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + if (s->insert > s->strstart) + s->insert = s->strstart; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + /* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ +int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, + int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ +int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, int strategy, + const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; @@ -11144,7 +11180,11 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, * symbols from which it is being constructed. */ +#ifdef LIT_MEM + s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 5); +#else s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4); +#endif s->pending_buf_size = (ulg)s->lit_bufsize * 4; if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || @@ -11154,8 +11194,14 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, deflateEnd (strm); return Z_MEM_ERROR; } +#ifdef LIT_MEM + s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); + s->l_buf = s->pending_buf + (s->lit_bufsize << 2); + s->sym_end = s->lit_bufsize - 1; +#else s->sym_buf = s->pending_buf + s->lit_bufsize; s->sym_end = (s->lit_bufsize - 1) * 3; +#endif /* We avoid equality with lit_bufsize*3 because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. @@ -11171,9 +11217,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -local int deflateStateCheck(strm) - z_streamp strm; -{ +local int deflateStateCheck(z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) @@ -11194,11 +11238,8 @@ local int deflateStateCheck(strm) } /* ========================================================================= */ -int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ +int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { deflate_state *s; uInt str, n; int wrap; @@ -11263,11 +11304,8 @@ int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) - z_streamp strm; - Bytef *dictionary; - uInt *dictLength; -{ +int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { deflate_state *s; uInt len; @@ -11285,9 +11323,7 @@ int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength) } /* ========================================================================= */ -int ZEXPORT deflateResetKeep(strm) - z_streamp strm; -{ +int ZEXPORT deflateResetKeep(z_streamp strm) { deflate_state *s; if (deflateStateCheck(strm)) { @@ -11317,15 +11353,37 @@ int ZEXPORT deflateResetKeep(strm) adler32(0L, Z_NULL, 0); s->last_flush = -2; - _tr_init(s); + _tr_init(s); + + return Z_OK; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init(deflate_state *s) { + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); - return Z_OK; + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; } /* ========================================================================= */ -int ZEXPORT deflateReset(strm) - z_streamp strm; -{ +int ZEXPORT deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); @@ -11335,10 +11393,7 @@ int ZEXPORT deflateReset(strm) } /* ========================================================================= */ -int ZEXPORT deflateSetHeader(strm, head) - z_streamp strm; - gz_headerp head; -{ +int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) { if (deflateStateCheck(strm) || strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; @@ -11346,11 +11401,7 @@ int ZEXPORT deflateSetHeader(strm, head) } /* ========================================================================= */ -int ZEXPORT deflatePending(strm, pending, bits) - unsigned *pending; - int *bits; - z_streamp strm; -{ +int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) { if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; @@ -11360,19 +11411,21 @@ int ZEXPORT deflatePending(strm, pending, bits) } /* ========================================================================= */ -int ZEXPORT deflatePrime(strm, bits, value) - z_streamp strm; - int bits; - int value; -{ +int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) { deflate_state *s; int put; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; +#ifdef LIT_MEM + if (bits < 0 || bits > 16 || + (uchf *)s->d_buf < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; +#else if (bits < 0 || bits > 16 || s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; +#endif do { put = Buf_size - s->bi_valid; if (put > bits) @@ -11387,11 +11440,7 @@ int ZEXPORT deflatePrime(strm, bits, value) } /* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ +int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; @@ -11436,13 +11485,8 @@ int ZEXPORT deflateParams(strm, level, strategy) } /* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ +int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy, + int nice_length, int max_chain) { deflate_state *s; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -11478,10 +11522,7 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) * * Shifts are used to approximate divisions, for speed. */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ +uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong fixedlen, storelen, wraplen; @@ -11537,7 +11578,8 @@ uLong ZEXPORT deflateBound(strm, sourceLen) /* if not default parameters, return one of the conservative bounds */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen; + return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) + + wraplen; /* default settings: return tight bound for that case -- ~0.03% overhead plus a small constant */ @@ -11550,10 +11592,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ -local void putShortMSB(s, b) - deflate_state *s; - uInt b; -{ +local void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } @@ -11564,9 +11603,7 @@ local void putShortMSB(s, b) * applications may wish to modify it to avoid allocating a large * strm->next_out buffer and copying into it. (See also read_buf()). */ -local void flush_pending(strm) - z_streamp strm; -{ +local void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; @@ -11597,10 +11634,7 @@ local void flush_pending(strm) } while (0) /* ========================================================================= */ -int ZEXPORT deflate(strm, flush) - z_streamp strm; - int flush; -{ +int ZEXPORT deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; @@ -11912,9 +11946,7 @@ int ZEXPORT deflate(strm, flush) } /* ========================================================================= */ -int ZEXPORT deflateEnd(strm) - z_streamp strm; -{ +int ZEXPORT deflateEnd(z_streamp strm) { int status; if (deflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -11938,11 +11970,10 @@ int ZEXPORT deflateEnd(strm) * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ -int ZEXPORT deflateCopy(dest, source) - z_streamp dest; - z_streamp source; -{ +int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K + (void)dest; + (void)source; return Z_STREAM_ERROR; #else deflate_state *ds; @@ -11980,7 +12011,12 @@ int ZEXPORT deflateCopy(dest, source) zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); +#ifdef LIT_MEM + ds->d_buf = (ushf *)(ds->pending_buf + (ds->lit_bufsize << 1)); + ds->l_buf = ds->pending_buf + (ds->lit_bufsize << 2); +#else ds->sym_buf = ds->pending_buf + ds->lit_bufsize; +#endif ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; @@ -11990,66 +12026,6 @@ int ZEXPORT deflateCopy(dest, source) #endif /* MAXSEG_64K */ } -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local unsigned read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - zmemcpy(buf, strm->next_in, len); - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, buf, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, buf, len); - } -#endif - strm->next_in += len; - strm->total_in += len; - - return len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init(s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->insert = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -} - #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and @@ -12060,10 +12036,7 @@ local void lm_init(s) * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ +local uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ @@ -12211,10 +12184,7 @@ local uInt longest_match(s, cur_match) /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ +local uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ @@ -12262,173 +12232,38 @@ local uInt longest_match(s, cur_match) if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#endif /* FASTEST */ - -#ifdef ZLIB_DEBUG - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start - match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* ZLIB_DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - unsigned n; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize + MAX_DIST(s)) { - - zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - if (s->insert > s->strstart) - s->insert = s->strstart; - slide_hash(s); - more += wsize; - } - if (s->strm->avail_in == 0) break; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { - uInt str = s->strstart - s->insert; - s->ins_h = s->window[str]; - UPDATE_HASH(s, s->ins_h, s->window[str + 1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - while (s->insert) { - UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); -#ifndef FASTEST - s->prev[str & s->w_mask] = s->head[s->ins_h]; -#endif - s->head[s->ins_h] = (Pos)str; - str++; - s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) - break; - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ - if (s->high_water < s->window_size) { - ulg curr = s->strstart + (ulg)(s->lookahead); - ulg init; - - if (s->high_water < curr) { - /* Previous high water mark below current data -- zero WIN_INIT - * bytes or up to end of window, whichever is less. - */ - init = s->window_size - curr; - if (init > WIN_INIT) - init = WIN_INIT; - zmemzero(s->window + curr, (unsigned)init); - s->high_water = curr + init; - } - else if (s->high_water < (ulg)curr + WIN_INIT) { - /* High water mark at or above current data, but below current data - * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up - * to end of window, whichever is less. - */ - init = (ulg)curr + WIN_INIT - s->high_water; - if (init > s->window_size - s->high_water) - init = s->window_size - s->high_water; - zmemzero(s->window + s->high_water, (unsigned)init); - s->high_water += init; - } - } + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} - Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, - "not enough room for search"); +#endif /* FASTEST */ + +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(deflate_state *s, IPos start, IPos match, int length) { + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start - match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } } +#else +# define check_match(s, start, match, length) +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Flush the current block, with given end-of-file flag. @@ -12472,10 +12307,7 @@ local void fill_window(s) * copied. It is most efficient with large input and output buffers, which * maximizes the opportunities to have a single copy from next_in to next_out. */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_stored(deflate_state *s, int flush) { /* Smallest worthy block size when not flushing or finishing. By default * this is 32K. This can be as small as 507 bytes for memLevel == 1. For * large input and output buffers, the stored block size will be larger. @@ -12659,10 +12491,7 @@ local block_state deflate_stored(s, flush) * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ @@ -12761,10 +12590,7 @@ local block_state deflate_fast(s, flush) * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ @@ -12892,10 +12718,7 @@ local block_state deflate_slow(s, flush) * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ @@ -12966,10 +12789,7 @@ local block_state deflate_rle(s, flush) * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ -local block_state deflate_huff(s, flush) - deflate_state *s; - int flush; -{ +local block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { @@ -13026,13 +12846,11 @@ z_const char * const z_errmsg[10] = { }; -const char * ZEXPORT zlibVersion() -{ +const char * ZEXPORT zlibVersion(void) { return ZLIB_VERSION; } -uLong ZEXPORT zlibCompileFlags() -{ +uLong ZEXPORT zlibCompileFlags(void) { uLong flags; flags = 0; @@ -13123,9 +12941,7 @@ uLong ZEXPORT zlibCompileFlags() # endif int ZLIB_INTERNAL z_verbose = verbose; -void ZLIB_INTERNAL z_error(m) - char *m; -{ +void ZLIB_INTERNAL z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } @@ -13134,9 +12950,7 @@ void ZLIB_INTERNAL z_error(m) /* exported to allow conversion of error code to string for compress() and * uncompress() */ -const char * ZEXPORT zError(err) - int err; -{ +const char * ZEXPORT zError(int err) { return ERR_MSG(err); } @@ -13150,22 +12964,14 @@ const char * ZEXPORT zError(err) #ifndef HAVE_MEMCPY -void ZLIB_INTERNAL zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ +void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } -int ZLIB_INTERNAL zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ +int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) { uInt j; for (j = 0; j < len; j++) { @@ -13174,10 +12980,7 @@ int ZLIB_INTERNAL zmemcmp(s1, s2, len) return 0; } -void ZLIB_INTERNAL zmemzero(dest, len) - Bytef* dest; - uInt len; -{ +void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ @@ -13218,8 +13021,7 @@ local ptr_table table[MAX_PTR]; * a protected system like OS/2. Use Microsoft C instead. */ -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; @@ -13244,8 +13046,7 @@ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) return buf; } -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { int n; (void)opaque; @@ -13281,14 +13082,12 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) # define _hfree hfree #endif -voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } -void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } @@ -13301,25 +13100,18 @@ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); +extern voidp malloc(uInt size); +extern voidp calloc(uInt items, uInt size); +extern void free(voidpf ptr); #endif -voidpf ZLIB_INTERNAL zcalloc(opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ +voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) { (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } -void ZLIB_INTERNAL zcfree(opaque, ptr) - voidpf opaque; - voidpf ptr; -{ +void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) { (void)opaque; free(ptr); } @@ -13348,13 +13140,8 @@ void ZLIB_INTERNAL zcfree(opaque, ptr) memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -int ZEXPORT compress2(dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ +int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen, int level) { z_stream stream; int err; const uInt max = (uInt)-1; @@ -13394,12 +13181,8 @@ int ZEXPORT compress2(dest, destLen, source, sourceLen, level) /* =========================================================================== */ -int ZEXPORT compress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } @@ -13407,9 +13190,7 @@ int ZEXPORT compress(dest, destLen, source, sourceLen) If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -uLong ZEXPORT compressBound(sourceLen) - uLong sourceLen; -{ +uLong ZEXPORT compressBound(uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } @@ -13439,12 +13220,8 @@ uLong ZEXPORT compressBound(sourceLen) Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ -int ZEXPORT uncompress2(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong *sourceLen; -{ +int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong *sourceLen) { z_stream stream; int err; const uInt max = (uInt)-1; @@ -13498,12 +13275,8 @@ int ZEXPORT uncompress2(dest, destLen, source, sourceLen) err; } -int ZEXPORT uncompress(dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ +int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, + uLong sourceLen) { return uncompress2(dest, destLen, source, &sourceLen); } /* trees.c -- output deflated data using Huffman coding @@ -13759,39 +13532,116 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local const static_tree_desc static_l_desc = +#ifdef NO_INIT_GLOBAL_POINTERS +# define TCONST +#else +# define TCONST const +#endif + +local TCONST static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local const static_tree_desc static_d_desc = +local TCONST static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local const static_tree_desc static_bl_desc = +local TCONST static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== - * Local (static) routines in this file. + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(unsigned code, int len) { + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(deflate_state *s) { + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(deflate_state *s) { + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->bits_sent = (s->bits_sent + 7) & ~7; +#endif +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. */ +local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) { + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits - 1]) << 1; + next_code[bits] = (ush)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, const ct_data *ltree, - const ct_data *dtree)); -local int detect_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned code, int len)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); + } +} #ifdef GEN_TREES_H -local void gen_trees_header OF((void)); +local void gen_trees_header(void); #endif #ifndef ZLIB_DEBUG @@ -13804,27 +13654,12 @@ local void gen_trees_header OF((void)); send_bits(s, tree[c].Code, tree[c].Len); } #endif -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef ZLIB_DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ +local void send_bits(deflate_state *s, int value, int length) { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; @@ -13866,8 +13701,7 @@ local void send_bits(s, value, length) /* =========================================================================== * Initialize the various 'constant' tables. */ -local void tr_static_init() -{ +local void tr_static_init(void) { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ @@ -13960,8 +13794,7 @@ local void tr_static_init() ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width) - 1 ? ",\n" : ", ")) -void gen_trees_header() -{ +void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; @@ -14010,12 +13843,26 @@ void gen_trees_header() } #endif /* GEN_TREES_H */ +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(deflate_state *s) { + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->sym_next = s->matches = 0; +} + /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ -void ZLIB_INTERNAL _tr_init(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; @@ -14038,24 +13885,6 @@ void ZLIB_INTERNAL _tr_init(s) init_block(s); } -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->sym_next = s->matches = 0; -} - #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ @@ -14085,11 +13914,7 @@ local void init_block(s) * when the heap property is re-established (each father smaller than its * two sons). */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ +local void pqdownheap(deflate_state *s, ct_data *tree, int k) { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { @@ -14120,10 +13945,7 @@ local void pqdownheap(s, tree, k) * The length opt_len is updated; static_len is also updated if stree is * not null. */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ +local void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; @@ -14198,48 +14020,9 @@ local void gen_bitlen(s, desc) } } -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes(tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - unsigned code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - code = (code + bl_count[bits - 1]) << 1; - next_code[bits] = (ush)code; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = (ush)bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1)); - } -} +#ifdef DUMP_BL_TREE +# include +#endif /* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. @@ -14249,10 +14032,7 @@ local void gen_codes(tree, max_code, bl_count) * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ +local void build_tree(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; @@ -14337,11 +14117,7 @@ local void build_tree(s, desc) * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ -local void scan_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ +local void scan_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -14382,11 +14158,7 @@ local void scan_tree(s, tree, max_code) * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ -local void send_tree(s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ +local void send_tree(deflate_state *s, ct_data *tree, int max_code) { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ @@ -14433,9 +14205,7 @@ local void send_tree(s, tree, max_code) * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ -local int build_bl_tree(s) - deflate_state *s; -{ +local int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ @@ -14468,10 +14238,8 @@ local int build_bl_tree(s) * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ +local void send_all_trees(deflate_state *s, int lcodes, int dcodes, + int blcodes) { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); @@ -14497,12 +14265,8 @@ local void send_all_trees(s, lcodes, dcodes, blcodes) /* =========================================================================== * Send a stored block */ -void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */ bi_windup(s); /* align on byte boundary */ put_short(s, (ush)stored_len); @@ -14521,9 +14285,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ -void ZLIB_INTERNAL _tr_flush_bits(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) { bi_flush(s); } @@ -14531,9 +14293,7 @@ void ZLIB_INTERNAL _tr_flush_bits(s) * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ -void ZLIB_INTERNAL _tr_align(s) - deflate_state *s; -{ +void ZLIB_INTERNAL _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef ZLIB_DEBUG @@ -14542,16 +14302,108 @@ void ZLIB_INTERNAL _tr_align(s) bi_flush(s); } +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(deflate_state *s, const ct_data *ltree, + const ct_data *dtree) { + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned sx = 0; /* running index in symbol buffers */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->sym_next != 0) do { +#ifdef LIT_MEM + dist = s->d_buf[sx]; + lc = s->l_buf[sx++]; +#else + dist = s->sym_buf[sx++] & 0xff; + dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; + lc = s->sym_buf[sx++]; +#endif + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code + LITERALS + 1, ltree); /* send length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check for no overlay of pending_buf on needed symbols */ +#ifdef LIT_MEM + Assert(s->pending < (s->lit_bufsize << 1) + sx, "pendingBuf overflow"); +#else + Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); +#endif + + } while (sx < s->sym_next); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "block list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(deflate_state *s) { + /* block_mask is the bit mask of block-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long block_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("block-listed") bytes. */ + for (n = 0; n <= 31; n++, block_mask >>= 1) + if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("allow-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "block-listed" or "allow-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and write out the encoded block. */ -void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int last; /* one if this is the last block for a file */ -{ +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last) { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ @@ -14648,14 +14500,15 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ -int ZLIB_INTERNAL _tr_tally(s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */ -{ +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) { +#ifdef LIT_MEM + s->d_buf[s->sym_next] = (ush)dist; + s->l_buf[s->sym_next++] = (uch)lc; +#else s->sym_buf[s->sym_next++] = (uch)dist; s->sym_buf[s->sym_next++] = (uch)(dist >> 8); s->sym_buf[s->sym_next++] = (uch)lc; +#endif if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; @@ -14672,150 +14525,6 @@ int ZLIB_INTERNAL _tr_tally(s, dist, lc) } return (s->sym_next == s->sym_end); } - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - const ct_data *ltree; /* literal tree */ - const ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned sx = 0; /* running index in sym_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->sym_next != 0) do { - dist = s->sym_buf[sx++] & 0xff; - dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8; - lc = s->sym_buf[sx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code + LITERALS + 1, ltree); /* send length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= (unsigned)base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and sym_buf is ok: */ - Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow"); - - } while (sx < s->sym_next); - - send_code(s, END_BLOCK, ltree); -} - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "block list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local int detect_data_type(s) - deflate_state *s; -{ - /* block_mask is the bit mask of block-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - unsigned long block_mask = 0xf3ffc07fUL; - int n; - - /* Check for non-textual ("block-listed") bytes. */ - for (n = 0; n <= 31; n++, block_mask >>= 1) - if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0)) - return Z_BINARY; - - /* Check for textual ("allow-listed") bytes. */ - if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 - || s->dyn_ltree[13].Freq != 0) - return Z_TEXT; - for (n = 32; n < LITERALS; n++) - if (s->dyn_ltree[n].Freq != 0) - return Z_TEXT; - - /* There are no "block-listed" or "allow-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef ZLIB_DEBUG - s->bits_sent = (s->bits_sent + 7) & ~7; -#endif -} /* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -14859,8 +14568,8 @@ typedef struct { examples/enough.c found in the zlib distribution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the + returns 852, and "enough 30 6 15" for distance codes returns 592. The + initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ @@ -14875,11 +14584,11 @@ typedef enum { DISTS } codetype; -int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work); /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2022 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -14889,7 +14598,7 @@ int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; + " inflate 1.3.0.1 Copyright 1995-2023 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -14909,14 +14618,9 @@ const char inflate_copyright[] = table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ +int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ @@ -14942,7 +14646,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 70, 200}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -15192,7 +14896,7 @@ unsigned short FAR *work; subject to change. Applications should only use zlib.h. */ -void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start); /* inflate.h -- internal inflate state definition * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -15368,10 +15072,7 @@ struct inflate_state { requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void ZLIB_INTERNAL inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ +void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ @@ -15735,20 +15436,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ # endif #endif -/* function prototypes */ -local int inflateStateCheck OF((z_streamp strm)); -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, - unsigned copy)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, - unsigned len)); - -local int inflateStateCheck(strm) -z_streamp strm; -{ +local int inflateStateCheck(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) @@ -15760,9 +15448,7 @@ z_streamp strm; return 0; } -int ZEXPORT inflateResetKeep(strm) -z_streamp strm; -{ +int ZEXPORT inflateResetKeep(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -15786,9 +15472,7 @@ z_streamp strm; return Z_OK; } -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ +int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -15799,10 +15483,7 @@ z_streamp strm; return inflateResetKeep(strm); } -int ZEXPORT inflateReset2(strm, windowBits) -z_streamp strm; -int windowBits; -{ +int ZEXPORT inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state FAR *state; @@ -15839,12 +15520,8 @@ int windowBits; return inflateReset(strm); } -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ +int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size) { int ret; struct inflate_state FAR *state; @@ -15883,22 +15560,17 @@ int stream_size; return ret; } -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ +int ZEXPORT inflateInit_(z_streamp strm, const char *version, + int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ +int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; @@ -15922,9 +15594,7 @@ int value; used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ +local void fixedtables(struct inflate_state FAR *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; @@ -16081,7 +15751,7 @@ struct inflate_state FAR *state; a.out > inffixed.h */ -void makefixed() +void makefixed(void) { unsigned low, size; struct inflate_state state; @@ -16135,11 +15805,7 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, end, copy) -z_streamp strm; -const Bytef *end; -unsigned copy; -{ +local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) { struct inflate_state FAR *state; unsigned dist; @@ -16361,10 +16027,7 @@ unsigned copy; will return Z_BUF_ERROR if it has not reached the end of the stream. */ -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ +int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ @@ -17040,9 +16703,7 @@ int flush; return ret; } -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ +int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -17054,11 +16715,8 @@ z_streamp strm; return Z_OK; } -int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) -z_streamp strm; -Bytef *dictionary; -uInt *dictLength; -{ +int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary, + uInt *dictLength) { struct inflate_state FAR *state; /* check state */ @@ -17077,11 +16735,8 @@ uInt *dictLength; return Z_OK; } -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ +int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, + uInt dictLength) { struct inflate_state FAR *state; unsigned long dictid; int ret; @@ -17112,10 +16767,7 @@ uInt dictLength; return Z_OK; } -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ +int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state FAR *state; /* check state */ @@ -17140,11 +16792,8 @@ gz_headerp head; called again with more data and the *have state. *have is initialized to zero for the first call. */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -const unsigned char FAR *buf; -unsigned len; -{ +local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf, + unsigned len) { unsigned got; unsigned next; @@ -17163,9 +16812,7 @@ unsigned len; return next; } -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ +int ZEXPORT inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ @@ -17180,7 +16827,7 @@ z_streamp strm; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; - state->hold <<= state->bits & 7; + state->hold >>= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { @@ -17221,9 +16868,7 @@ z_streamp strm; block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ +int ZEXPORT inflateSyncPoint(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -17231,10 +16876,7 @@ z_streamp strm; return state->mode == STORED && state->bits == 0; } -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ +int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; @@ -17278,10 +16920,7 @@ z_streamp source; return Z_OK; } -int ZEXPORT inflateUndermine(strm, subvert) -z_streamp strm; -int subvert; -{ +int ZEXPORT inflateUndermine(z_streamp strm, int subvert) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -17296,10 +16935,7 @@ int subvert; #endif } -int ZEXPORT inflateValidate(strm, check) -z_streamp strm; -int check; -{ +int ZEXPORT inflateValidate(z_streamp strm, int check) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; @@ -17311,9 +16947,7 @@ int check; return Z_OK; } -long ZEXPORT inflateMark(strm) -z_streamp strm; -{ +long ZEXPORT inflateMark(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) @@ -17324,9 +16958,7 @@ z_streamp strm; (state->mode == MATCH ? state->was - state->length : 0)); } -unsigned long ZEXPORT inflateCodesUsed(strm) -z_streamp strm; -{ +unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return (unsigned long)-1; state = (struct inflate_state FAR *)strm->state; diff --git a/src/include/sys-zlib.h b/src/include/sys-zlib.h index dd9ccc4b17..af7e554006 100644 --- a/src/include/sys-zlib.h +++ b/src/include/sys-zlib.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////// // File: sys-zlib.h // Home: https://github.com/Siskin-framework/Rebol-Zlib -// Date: 25-Jan-2023 +// Date: 4-Jan-2024 // Note: This file is amalgamated from these sources: // // zconf.h @@ -259,7 +259,11 @@ #endif #ifdef Z_SOLO - typedef unsigned long z_size_t; +# ifdef _WIN64 + typedef unsigned long long z_size_t; +# else + typedef unsigned long z_size_t; +# endif #else # define z_longlong long long # if defined(NO_SIZE_T) @@ -538,7 +542,7 @@ typedef uLong FAR uLongf; #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# if defined(_WIN32) && !defined(__GNUC__) # define z_off64_t __int64 # else # define z_off64_t z_off_t @@ -756,9 +760,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); #endif /* common defaults */ @@ -797,16 +801,16 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define zmemzero(dest, len) memset(dest, 0, len) # endif #else - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); + void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len); + int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len); + void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL z_error OF((char *m)); + extern void ZLIB_INTERNAL z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -823,9 +827,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, + unsigned size); + void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ @@ -839,9 +843,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif /* ZUTIL_H */ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.13, October 13th, 2022 + version 1.3.0.1, August xxth, 2023 - Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -877,12 +881,12 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ extern "C" { #endif -#define ZLIB_VERSION "1.2.13" -#define ZLIB_VERNUM 0x12d0 +#define ZLIB_VERSION "1.3.0.1-motley" +#define ZLIB_VERNUM 0x1301 #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 13 -#define ZLIB_VER_SUBREVISION 0 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 +#define ZLIB_VER_SUBREVISION 1 /* The 'zlib' compression library provides in-memory compression and @@ -918,8 +922,8 @@ extern "C" { even in the case of corrupted input. */ -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); +typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size); +typedef void (*free_func)(voidpf opaque, voidpf address); struct internal_state; @@ -1057,7 +1061,7 @@ typedef gz_header FAR *gz_headerp; /* basic functions */ -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +ZEXTERN const char * ZEXPORT zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check @@ -1065,12 +1069,12 @@ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); */ /* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); +ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all @@ -1087,7 +1091,7 @@ ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); */ -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -1160,8 +1164,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was @@ -1200,7 +1204,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); */ -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending @@ -1215,7 +1219,7 @@ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by @@ -1223,7 +1227,8 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates - them to use default allocation functions. + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -1237,7 +1242,7 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); */ -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce @@ -1357,7 +1362,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); */ -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending @@ -1375,12 +1380,12 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); */ /* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); +ZEXTERN int ZEXPORT deflateInit2(z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. @@ -1447,9 +1452,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this @@ -1491,9 +1496,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ -ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied @@ -1513,8 +1518,8 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, stream state is inconsistent. */ -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT deflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -1531,20 +1536,20 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been - set unchanged. + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); +ZEXTERN int ZEXPORT deflateParams(z_streamp strm, + int level, + int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be @@ -1569,7 +1574,7 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). + applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if @@ -1580,11 +1585,11 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, retried with more output space. */ -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); +ZEXTERN int ZEXPORT deflateTune(z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for @@ -1597,8 +1602,8 @@ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); +ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, + uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or @@ -1612,9 +1617,9 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, than Z_FINISH or Z_NO_FLUSH are used. */ -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); +ZEXTERN int ZEXPORT deflatePending(z_streamp strm, + unsigned *pending, + int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not @@ -1627,9 +1632,9 @@ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT deflatePrime(z_streamp strm, + int bits, + int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits @@ -1644,8 +1649,8 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, source stream state was inconsistent. */ -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm, + gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called @@ -1661,16 +1666,17 @@ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateInit2(z_streamp strm, + int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized @@ -1723,9 +1729,9 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, deferred until inflate() is called. */ -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); +ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm, + const Bytef *dictionary, + uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, @@ -1746,9 +1752,9 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ -ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, - Bytef *dictionary, - uInt *dictLength)); +ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm, + Bytef *dictionary, + uInt *dictLength); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied @@ -1761,7 +1767,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, stream state is inconsistent. */ -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all @@ -1774,14 +1780,14 @@ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of - total_in which indicates where valid compressed data was found. In the - error case, the application may repeatedly call inflateSync, providing more - input each time, until success or end of the input data. + In the success case, the application may save the current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. */ -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); +ZEXTERN int ZEXPORT inflateCopy(z_streamp dest, + z_streamp source); /* Sets the destination stream as a complete copy of the source stream. @@ -1796,18 +1802,19 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, destination. */ -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); +ZEXTERN int ZEXPORT inflateReset2(z_streamp strm, + int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted @@ -1820,9 +1827,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, the windowBits parameter is invalid. */ -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); +ZEXTERN int ZEXPORT inflatePrime(z_streamp strm, + int bits, + int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the @@ -1841,7 +1848,7 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, stream state was inconsistent. */ -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +ZEXTERN long ZEXPORT inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the @@ -1869,8 +1876,8 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); source stream state was inconsistent. */ -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); +ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm, + gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after @@ -1910,8 +1917,8 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, */ /* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); +ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits, + unsigned char FAR *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized @@ -1931,13 +1938,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, - z_const unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); +typedef unsigned (*in_func)(void FAR *, + z_const unsigned char FAR * FAR *); +typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned); -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack(z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than @@ -2005,7 +2012,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, cannot return Z_OK. */ -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. @@ -2013,7 +2020,7 @@ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); state was inconsistent. */ -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +ZEXTERN uLong ZEXPORT zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: @@ -2066,8 +2073,8 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); you need special options. */ -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size @@ -2081,9 +2088,9 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, buffer. */ -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); +ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte @@ -2097,15 +2104,15 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, Z_STREAM_ERROR if the level parameter is invalid. */ -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); +ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size @@ -2122,8 +2129,8 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ -ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong *sourceLen)); +ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of @@ -2142,7 +2149,7 @@ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") @@ -2179,7 +2186,7 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); file could not be opened. */ -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has @@ -2202,7 +2209,7 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); will not detect if fd is invalid (unless fd is -1). */ -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called @@ -2218,7 +2225,7 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); too late. */ -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously @@ -2229,7 +2236,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); or Z_MEM_ERROR if there is a memory allocation error. */ -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of @@ -2259,8 +2266,8 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); Z_STREAM_ERROR. */ -ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, - gzFile file)); +ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, + gzFile file); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of @@ -2285,14 +2292,14 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, file, resetting and retrying on end-of-file, when size is not 1. */ -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); +ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ -ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, - z_size_t nitems, gzFile file)); +ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, + z_size_t nitems, gzFile file); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If @@ -2305,7 +2312,7 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, is returned, and the error state is set to Z_STREAM_ERROR. */ -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of @@ -2320,7 +2327,7 @@ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); This can be determined using zlibCompileFlags(). */ -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. @@ -2328,7 +2335,7 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); gzputs returns the number of characters written, or -1 in case of error. */ -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an @@ -2342,13 +2349,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); buf are indeterminate. */ -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +ZEXTERN int ZEXPORT gzputc(gzFile file, int c); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +ZEXTERN int ZEXPORT gzgetc(gzFile file); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. @@ -2357,7 +2364,7 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); points to has been clobbered or not. */ -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +ZEXTERN int ZEXPORT gzungetc(int c, gzFile file); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. @@ -2369,7 +2376,7 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); gzseek() or gzrewind(). */ -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +ZEXTERN int ZEXPORT gzflush(gzFile file, int flush); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function @@ -2385,8 +2392,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); */ /* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); +ZEXTERN z_off_t ZEXPORT gzseek(gzFile file, + z_off_t offset, int whence); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the @@ -2404,7 +2411,7 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, would be before the current position. */ -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +ZEXTERN int ZEXPORT gzrewind(gzFile file); /* Rewind file. This function is supported only for reading. @@ -2412,7 +2419,7 @@ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); */ /* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gztell(gzFile file); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, @@ -2423,7 +2430,7 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); */ /* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); +ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example @@ -2432,7 +2439,7 @@ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); be used for a progress indicator. On error, gzoffset() returns -1. */ -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +ZEXTERN int ZEXPORT gzeof(gzFile file); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set @@ -2447,7 +2454,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); has grown since the previous end of file was detected. */ -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +ZEXTERN int ZEXPORT gzdirect(gzFile file); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. @@ -2468,7 +2475,7 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); gzip file reading and decompression, which may not be desired.) */ -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose(gzFile file); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you @@ -2481,8 +2488,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); last read ended in the middle of a gzip stream, or Z_OK on success. */ -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_r(gzFile file); +ZEXTERN int ZEXPORT gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to @@ -2493,7 +2500,7 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); zlib library. */ -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system @@ -2509,7 +2516,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); functions above that do not distinguish those cases in their return values. */ -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +ZEXTERN void ZEXPORT gzclearerr(gzFile file); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip @@ -2526,7 +2533,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); library. */ -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit @@ -2546,15 +2553,15 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ -ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, + z_size_t len); /* Same as adler32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); +ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, + z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for @@ -2564,7 +2571,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, negative, the result has no meaning or utility. */ -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. @@ -2582,14 +2589,14 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ -ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, - z_size_t len)); +ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf, + z_size_t len); /* Same as crc32(), but with a size_t length. */ /* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); +ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were @@ -2599,13 +2606,13 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); */ /* -ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); +ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2); Return the operator corresponding to length len2, to be used with crc32_combine_op(). */ -ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); +ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than @@ -2618,20 +2625,20 @@ ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); +ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateInit_(z_streamp strm, + const char *version, int stream_size); +ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size); +ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size); +ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) @@ -2676,7 +2683,7 @@ struct gzFile_s { unsigned char *next; z_off64_t pos; }; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ @@ -2693,13 +2700,13 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int); + ZEXTERN z_off64_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) @@ -2721,50 +2728,50 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell64(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t); # endif #else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); + ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *); + ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int); + ZEXTERN z_off_t ZEXPORT gztell(gzFile); + ZEXTERN z_off_t ZEXPORT gzoffset(gzFile); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif #else /* Z_SOLO */ - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); + ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t); + ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); -ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +ZEXTERN const char * ZEXPORT zError(int); +ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void); +ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int); +ZEXTERN int ZEXPORT inflateValidate(z_streamp, int); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp); +ZEXTERN int ZEXPORT inflateResetKeep(z_streamp); +ZEXTERN int ZEXPORT deflateResetKeep(z_streamp); #if defined(_WIN32) && !defined(Z_SOLO) -ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, - const char *mode)); +ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path, + const char *mode); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO -ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, - const char *format, - va_list va)); +ZEXTERN int ZEXPORTVA gzvprintf(gzFile file, + const char *format, + va_list va); # endif #endif @@ -2798,6 +2805,10 @@ ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, # define GZIP #endif +/* define LIT_MEM to slightly increase the speed of deflate (order 1% to 2%) at + the cost of a larger memory footprint */ +/* #define LIT_MEM */ + /* =========================================================================== * Internal compression state. */ @@ -2992,7 +3003,12 @@ typedef struct internal_state { /* Depth of each subtree used as tie breaker for trees of equal frequency */ +#ifdef LIT_MEM + ushf *d_buf; /* buffer for distances */ + uchf *l_buf; /* buffer for literals/lengths */ +#else uchf *sym_buf; /* buffer for distances and literals/lengths */ +#endif uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for @@ -3014,7 +3030,7 @@ typedef struct internal_state { * - I can't count above 4 */ - uInt sym_next; /* running index in sym_buf */ + uInt sym_next; /* running index in symbol buffer */ uInt sym_end; /* symbol table full when sym_next reaches this */ ulg opt_len; /* bit length of current block with optimal trees */ @@ -3066,14 +3082,14 @@ typedef struct internal_state { memory checker errors from longest match routines */ /* in trees.c */ -void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); -int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); -void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); -void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, - ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_init(deflate_state *s); +int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc); +void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf, + ulg stored_len, int last); +void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s); +void ZLIB_INTERNAL _tr_align(deflate_state *s); +void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf, + ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) @@ -3093,6 +3109,25 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, extern const uch ZLIB_INTERNAL _dist_code[]; #endif +#ifdef LIT_MEM +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->sym_next] = 0; \ + s->l_buf[s->sym_next++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->d_buf[s->sym_next] = dist; \ + s->l_buf[s->sym_next++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->sym_next == s->sym_end); \ + } +#else # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->sym_buf[s->sym_next++] = 0; \ @@ -3112,6 +3147,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->sym_next == s->sym_end); \ } +#endif #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ From 27611e9d02764593484a1c8c9aac151c907145cc Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 4 Jan 2024 15:30:39 +0100 Subject: [PATCH 29/60] FEAT: including source of `webdriver` and `websocket` modules --- README.md | 2 + src/boot/sysobj.reb | 2 + src/modules/webdriver.reb | 218 +++++++++++++++++++++++++++++++++ src/modules/websocket.reb | 247 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 469 insertions(+) create mode 100644 src/modules/webdriver.reb create mode 100644 src/modules/websocket.reb diff --git a/README.md b/README.md index 9679918b21..74a6aa6aca 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ It is possible to extend Rebol functionality using external modules (native and * [Rebol/OpenCV](https://github.com/Oldes/Rebol-OpenCV) - Computer Vision Library * [Rebol/SQLite](https://github.com/Siskin-framework/Rebol-SQLite) - SQL database engine * [Rebol/Triangulate](https://github.com/Siskin-framework/Rebol-Triangulate) - Two-Dimensional Quality Mesh Generator and Delaunay Triangulator +* [Rebol/WebDriver](https://github.com/Oldes/Rebol-WebDriver) - WebDriver scheme for automating Chromium based browser sessions +* [Rebol/WebSocket](https://github.com/Oldes/Rebol-WebSocket) - WebSocket scheme and codec It should be noted that on macOS it may be required to resign _downloaded native extensions_ using command like: ``` diff --git a/src/boot/sysobj.reb b/src/boot/sysobj.reb index 03dea94929..5e819683de 100644 --- a/src/boot/sysobj.reb +++ b/src/boot/sysobj.reb @@ -271,6 +271,8 @@ modules: object [ mime-field: https://src.rebol.tech/mezz/codec-mime-field.reb mime-types: https://src.rebol.tech/mezz/codec-mime-types.reb quoted-printable: https://src.rebol.tech/mezz/codec-quoted-printable.reb + webdriver: https://src.rebol.tech/modules/webdriver.reb + websocket: https://src.rebol.tech/modules/websocket.reb ;; and.. window: none ;- internal extension for gui (on Windows so far!) ] diff --git a/src/modules/webdriver.reb b/src/modules/webdriver.reb new file mode 100644 index 0000000000..b11979f6d7 --- /dev/null +++ b/src/modules/webdriver.reb @@ -0,0 +1,218 @@ +Rebol [ + Title: "WebDriver (chrome) scheme" + Type: module + Name: webdriver + Date: 03-Jan-2024 + Version: 0.1.0 + Author: @Oldes + Home: https://github.com/Oldes/Rebol-WebDriver + Rights: http://opensource.org/licenses/Apache-2.0 + Purpose: {Can be used to automate browser sessions.} + History: [ + 03-Jan-2024 "Oldes" {Initial version} + ] + Needs: [ + 3.11.0 ;; Minimal Rebol version required by WebScocket module + websocket + json + ] + Notes: { + Currently only `chrome` scheme is implemented which is supposed to be working + with Chromium, Chrome and other Blink-based browsers. + + The browser must be started with `remote-debugging` enabled. + + For example on macOS using a Brave browser: + ```terminal + /Applications/Brave\ Browser.app/Contents/MacOS/Brave\ Browser --remote-debugging-port=9222 + ``` + + Available methods are documented here: https://chromedevtools.github.io/devtools-protocol/ + } +] + +system/options/log/chrome: 4 + +;; internal functions.... +read-and-wait: function[ + "Wait specified time while processing read events" + port [port!] "Internal websocket port of the webdrive scheme" + time [time!] +][ + start: now/precise + end: start + time + until [ + read port + wait [port time] + + process-packets port + + time: difference end now/precise + time <= 0:0:0 + ] +] + +process-packets: function[ + "Process incomming webscocket packets of the webdrive scheme" + conn [port!] +][ + port: conn/parent ;; outter webdrive scheme + ctx: port/extra + foreach packet conn/data [ + try/with [ + packet: decode 'json packet + either packet/id [ + ctx/pending: ctx/pending - 1 + append port/data packet + ][ port/actor/on-method packet ] + ] :print + ] + clear conn/data +] + +ws-decode: :codecs/ws/decode + +;- The Chrome scheme --------------------------------------------------------------- +sys/make-scheme [ + name: 'chrome + title: "Chrome WebDriver API" + spec: object [title: scheme: ref: host: none port: 9222] + + actor: [ + open: func [port [port!] /local ctx spec host conn data port-spec][ + spec: port/spec + spec/host: any [spec/host "localhost"] + spec/port: any [spec/port 9222] + + port/data: copy [] ;; holds decoded websocket responses + port/extra: ctx: context [ + host: rejoin [http:// spec/host #":" spec/port] + version: none + browser: none + counter: 0 + pending: 0 ;; increments when a new method is sent, decremented when response is received + req: #(id: 0 method: none params: #[none]) ;; used to send a command (to avoid cerating a new map) + page-info: none ;; holds resolved info from an attached page + page-conn: none ;; webscocket connection to an attached page + ] + + ctx/version: data: try/with [ + decode 'json read ctx/host/json/version + ][ + sys/log/error 'CHROME "Failed to get browser info!" + sys/log/error 'CHROME system/state/last-error + return none + ] + + ctx/browser: conn: open as url! data/webSocketDebuggerUrl + conn/parent: port + wait [conn 15] + sys/log/more 'CHROME "Browser connection opened." + port + ] + open?: func[port /local ctx][ + all [ + ctx: port/extra + any [ctx/browser ctx/page-conn] + ] + ] + close: func[port /local ctx][ + ctx: port/extra + if ctx/port-conn [ + try [close ctx/port-conn wait [ctx/page-conn 1]] + ctx/port-conn: ctx/port-info: none + + ] + if ctx/browser [ + try [close ctx/browser wait [ctx/browser 1]] + ctx/browser: none + ] + port + ] + + write: func[port data /local ctx url time method params conn][ + unless block? data [data: reduce [data]] + + sys/log/info 'CHROME ["WRITE:" as-green mold/flat data] + + clear port/data + + ctx: port/extra + either open? ctx/browser [ + parse data [some [ + + set url: url! ( + ;- Open a new target (page) + try/with [ + ctx/page-info: decode 'json write join ctx/host/json/new? url [PUT] + ;?? ctx/page-info + append port/data ctx/page-info + + ctx/page-conn: conn: open as url! ctx/page-info/webSocketDebuggerUrl + ;conn/awake: :ws-web-awake + conn/parent: port + wait [conn 15] + conn: none + ] :print + ) + | set time: [time! | decimal! | integer!] ( + ;- Wait some time while processing incomming messages + time: to time! time + sys/log/info 'CHROME ["WAIT" as-green time] + read-and-wait any [ctx/page-conn ctx/browser] time + ) + | + set method: word! set params: opt [map! | block!] ( + ;- Send a command with optional options + if block? params [params: make map! reduce/no-set params] + sys/log/info 'CHROME ["Command:" as-red method as-green mold/flat/part params 100] + ;; resusing `req` value for all commands as it is just used to form a json anyway + ctx/req/id: ctx/counter: ctx/counter + 1 ;; each command has an unique id + ctx/req/method: method + ctx/req/params: params + ctx/pending: ctx/pending + 1 + write conn: any [ctx/page-conn ctx/browser] ctx/req + ;; don't wake up until received responses for all command requests + forever [ + ;@@TODO: handle the timeout to awoid infinite loop! + wait [conn 15] ;; wait for any events + process-packets conn ;; process incomming websocket messages + if ctx/pending <= 0 [break] ;; exit the loop if there are no pending requests + read conn ;; keep reading + ] + ) + ]] + either 1 = length? port/data [first port/data][port/data] + ][ sys/log/error 'CHROME "Not open!"] + ] + + read: func[port /local ctx conn packet][ + ;; waits for any number of incomming messages + if all [ + ctx: port/extra + conn: any [ctx/page-conn ctx/browser] + ][ + clear port/data + read conn + wait [conn 1] ;; don't wait more then 1 second if there are no incomming messages + process-packets conn + ] + port/data + ] + + pick: func[port value /local result][ + ;; just a shortcut to get a single result direcly + unless block? value [value: reduce [value]] + result: write port value + if block? result [result: last result] + result/result + ] + + on-method: func[packet][ + ;; this function is supposed to be user defined and used to process incomming messages + ;; in this case it just prints its content... + sys/log/info 'CHROME [as-red packet/method mold packet/params] + ] + ] +] + diff --git a/src/modules/websocket.reb b/src/modules/websocket.reb new file mode 100644 index 0000000000..3fc21f2aca --- /dev/null +++ b/src/modules/websocket.reb @@ -0,0 +1,247 @@ +Rebol [ + Title: "WebSocket scheme and codec" + Type: module + Name: websocket + Date: 01-Jan-2024 + Version: 0.1.0 + Author: @Oldes + Exports: [http-server decode-target to-CLF-idate] + Home: https://github.com/Oldes/Rebol-WebSocket + Rights: http://opensource.org/licenses/Apache-2.0 + Purpose: {Communicate with a server over WebSocket's connection.} + History: [ + 01-Jan-2024 "Oldes" {Initial version} + ] + Needs: [3.11.0] +] + +;--- WebSocket Codec -------------------------------------------------- +append system/options/log [ws: 4] +system/options/quiet: false +register-codec [ + name: 'ws + type: 'text + title: "WebSocket" + + encode: function/with [ + "Encodes one WebSocket message." + data [binary! any-string! word! map!] + /no-mask + ][ + case [ + data = 'ping [return #{81801B1F519C}] + data = 'close [return #{888260D19A196338}] + map? data [data: to-json data] + word? data [data: form data] + ] + out: clear #{} + ;; first byte has FIN bit and an opcode (if data are string or binary data) + byte1: either binary? data [2#10000010][2#10000001] ;; final binary/string + unless binary? data [data: to binary! data] + len: length? data + either no-mask [ + binary/write out case [ + len < 0#007E [[UI8 :byte1 UI8 :len :data]] + len <= 0#FFFF [[UI8 :byte1 UI8 126 UI16 :len :data]] + 'else [[UI8 :byte1 UI8 127 UI64 :len :data]] + ] + ][ + ;; update a mask... + repeat i 4 [mask/:i: 1 + random 254] ;; avoiding zero + data: data xor mask + binary/write out case [ + len < 0#007E [byte2: 2#10000000 | len [UI8 :byte1 UI8 :byte2 :mask :data]] + len <= 0#FFFF [[UI8 :byte1 UI8 254 UI16 :len :mask :data]] + 'else [[UI8 :byte1 UI8 255 UI64 :len :mask :data]] + ] + ] + out + ][ + mask: #{00000000} + out: make binary! 100 + ] + + decode: function [ + "Decodes WebSocket messages from a given input." + data [binary!] "Consumed data are removed! (modified)" + ][ + out: clear [] + ;; minimal WebSocket message has 2 bytes at least (when no masking involved) + while [2 < length? data][ + final?: data/1 & 2#10000000 = 2#10000000 + opcode: data/1 & 2#00001111 + mask?: data/2 & 2#10000000 = 2#10000000 + len: data/2 & 2#01111111 + data: skip data 2 + + ;@@ Not removing bytes until we make sure, that there is enough data! + case [ + len = 126 [ + ;; there must be at least 2 bytes for the message length + if 2 >= length? data [break] + len: binary/read data 'UI16 + data: skip data 2 + ] + len = 127 [ + if 8 >= length? data [break] + len: binary/read data 'UI64 + data: skip data 8 + ] + ] + if (4 + length? data) < len [break] + data: truncate data ;; removes already processed bytes from the head + either mask? [ + masks: take/part data 4 + temp: masks xor take/part data len + if len < 4 [truncate/part temp len] ;; the mask was longer then the message + ][ temp: take/part data len ] + if all [final? opcode = 1] [try [temp: to string! temp]] + append append append out :final? :opcode :temp + ] + out + ] +] + +ws-encode: :codecs/ws/encode +ws-decode: :codecs/ws/decode + +;--- WebSocket Scheme ------------------------------------------------- +ws-conn-awake: func [event /local port extra parent spec temp] [ + port: event/port + unless parent: port/parent [return true] + extra: parent/extra + sys/log/more 'WS ["==TCP-event:" as-red event/type] + either extra/handshake [ + switch event/type [ + read [ + append parent/data port/data + clear port/data + ] + ] + insert system/ports/system make event! [ type: event/type port: parent ] + port + ][ + switch/default event/type [ + ;- Upgrading from HTTP to WS...] + read [ + ;print ["^/read:" length? port/data] + append parent/data port/data + clear port/data + ;probe to string! parent/data + either find parent/data #{0D0A0D0A} [ + ;; parse response header... + try/with [ + ;; skip the first line and construct response fields + extra/fields: temp: construct find/tail parent/data #{0D0A} + unless all [ + "websocket" = select temp 'Upgrade + "Upgrade" = select temp 'Connection + extra/key = select temp 'Sec-WebSocket-Accept + ][ + insert system/ports/system make event! [ type: 'error port: parent ] + return true + ] + + ] :print + + clear port/data + clear parent/data + extra/handshake: true + insert system/ports/system make event! [ type: 'connect port: parent ] + ][ + ;; missing end of the response header... + read port + ] + ] + wrote [read port] + lookup [open port] + connect [ + spec: parent/spec + extra/key: enbase/part checksum form now/precise 'sha1 64 16 + write port ajoin [ + {GET } spec/path spec/target { HTTP/1.1} CRLF + {Host: } spec/host if spec/port [join #":" spec/port] CRLF + {Upgrade: websocket} CRLF + {Connection: Upgrade} CRLF + {Sec-WebSocket-Key: } extra/key CRLF + {Sec-WebSocket-Protocol: chat, superchat} CRLF + {Sec-WebSocket-Version: 13} CRLF + CRLF + ] + extra/key: enbase checksum join extra/key "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 'sha1 64 + ] + ][true] + ] +] +sys/make-scheme [ + name: 'ws + title: "Websocket" + spec: make system/standard/port-spec-net [] + awake: func [event /local port extra parent spec temp] [ + port: event/port + sys/log/debug 'WS ["== WS-event:" as-red event/type] + switch event/type [ + read [ + sys/log/debug 'WS ["== raw-data:" as-blue port/data] + ws-decode port/data + ] + wrote [] + connect [ + ;; optional validation of response headers + ?? port/extra/fields + ] + error [ + print "closing..." + try [close port/extra/connection] + ;wait port/extra/connection + ] + ] + true + ] + actor: [ + open: func [port [port!] /local spec host conn port-spec][ + spec: port/spec + port/extra: context [ + connection: + key: + handshake: + fields: none + ] + port/data: make binary! 200 + ;; `ref` is used in logging and errors + conn: make port/spec [ref: none] + conn/scheme: 'tcp + port-spec: if spec/port [join #":" spec/port] + conn/ref: as url! ajoin [conn/scheme "://" spec/host port-spec] + spec/ref: as url! ajoin ["ws://" spec/host port-spec] + port/extra/connection: conn: make port! conn + conn/parent: port + conn/awake: :ws-conn-awake + open conn + port + ] + open?: func[port /local ctx][ + all [ + ctx: port/extra + ctx/handshake + open? ctx/connection + ] + ] + close: func[port][ + close port/extra/connection + ] + write: func[port data][ + sys/log/debug 'WS ["write:" as-green mold data] + either open? port [ + write port/extra/connection ws-encode data + ][ sys/log/error 'WS "Not open!"] + + ] + read: func[port][ + either open? port [ + read port/extra/connection + ][ sys/log/error 'WS "Not open!"] + + ] + ] +] \ No newline at end of file From 45b358f075215b19490104891c2d8f64a578628e Mon Sep 17 00:00:00 2001 From: Oldes Date: Wed, 10 Jan 2024 00:03:19 +0100 Subject: [PATCH 30/60] FIX: close `httpd` server on request even when there are pending client connections --- src/modules/httpd.reb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/httpd.reb b/src/modules/httpd.reb index 760ec06cb2..9dec139d4c 100644 --- a/src/modules/httpd.reb +++ b/src/modules/httpd.reb @@ -2,8 +2,8 @@ Rebol [ Title: "HTTPd Scheme" Type: module Name: httpd - Date: 14-Dec-2023 - Version: 0.9.0 + Date: 10-Jan-2024 + Version: 0.9.1 Author: ["Andreas Bolka" "Christopher Ross-Gill" "Oldes"] Exports: [serve-http http-server decode-target to-CLF-idate] Home: https://github.com/Oldes/Rebol-HTTPd @@ -917,7 +917,7 @@ sys/make-scheme [ ;try [remove find clients port] ] log-debug ["Ports open:" length? clients] - if all [ctx/done? zero? length? clients][ + if ctx/done? [ log-more "Server's job done, closing initiated" ctx/parent/data: ctx/done? Awake-Server make event! [type: 'CLOSE port: ctx/parent] From aa7aa41114ba158d9e55fd3e291099229e3d15fb Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 11 Jan 2024 21:19:12 +0100 Subject: [PATCH 31/60] FIX: throw an error when converting `1.#NaN` value to integer --- src/core/t-integer.c | 2 +- src/tests/units/make-test.r3 | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/t-integer.c b/src/core/t-integer.c index f4772133d0..c3cc24206c 100644 --- a/src/core/t-integer.c +++ b/src/core/t-integer.c @@ -274,7 +274,7 @@ case A_TO: val = D_ARG(2); if (IS_DECIMAL(val) || IS_PERCENT(val)) { - if (VAL_DECIMAL(val) < MIN_D64 || VAL_DECIMAL(val) >= MAX_D64) + if (VAL_DECIMAL(val) < MIN_D64 || VAL_DECIMAL(val) >= MAX_D64 || isnan(VAL_DECIMAL(val))) Trap0(RE_OVERFLOW); num = (REBI64)VAL_DECIMAL(val); } diff --git a/src/tests/units/make-test.r3 b/src/tests/units/make-test.r3 index f37f13ab17..9ac8743c3c 100644 --- a/src/tests/units/make-test.r3 +++ b/src/tests/units/make-test.r3 @@ -140,6 +140,14 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/2099 --assert 302961000000 = to integer! "3.02961E+11" + --test-- "make/to integer! 1.#NaN and 1.#INF" + --assert error? try [to integer! 1.#NaN] + --assert error? try [to integer! 1.#INF] + --assert error? try [to integer! -1.#INF] + --assert error? try [make integer! 1.#NaN] + --assert error? try [make integer! 1.#INF] + --assert error? try [make integer! -1.#INF] + ===end-group=== ===start-group=== "make/to decimal!" From e401eddfb87ed47243984392bb445409b6fc390a Mon Sep 17 00:00:00 2001 From: Oldes Date: Thu, 11 Jan 2024 22:01:49 +0100 Subject: [PATCH 32/60] FEAT: Added `sum` and `average` functions --- src/mezz/mezz-math.reb | 20 ++++++++++++++++++++ src/tests/units/series-test.r3 | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/mezz/mezz-math.reb b/src/mezz/mezz-math.reb index c80ea823f0..dc309bb569 100644 --- a/src/mezz/mezz-math.reb +++ b/src/mezz/mezz-math.reb @@ -3,6 +3,7 @@ REBOL [ Title: "REBOL 3 Mezzanine: Math" Rights: { Copyright 2012 REBOL Technologies + Copyright 2012-2024 Rebol Open Source Developers REBOL is a trademark of REBOL Technologies } License: { @@ -93,3 +94,22 @@ find-max: func [ ] spot ] + +sum: func [ + "Returns the sum of all values in a block" + values [block! vector! paren!] + /local result value +][ + result: make any [values/1 0] 0 + foreach value values [result: result + value] + result +] + +average: func [ + "Returns the average of all values in a block" + block [block! vector! paren!] +][ + if empty? block [return none] + divide sum block length? block +] + diff --git a/src/tests/units/series-test.r3 b/src/tests/units/series-test.r3 index bfad132ace..e838d8ce36 100644 --- a/src/tests/units/series-test.r3 +++ b/src/tests/units/series-test.r3 @@ -2825,4 +2825,20 @@ Rebol [ ] ===end-group=== + +===start-group=== "SUM & AVERAGE" +--test-- "sum" + --assert 0 = sum [] + --assert 6 = sum [1 2 3] + --assert 6.0 = sum [1.0 2 3] + --assert 6 = sum #[uint8! [1 2 3]] +--test-- "average" + --assert none? average [] + --assert 2 = average [1 2 3] + --assert 2.0 = average [1.0 2 3] + --assert 2 = average #[uint8! [1 2 3]] + --assert 17.5 = average #[uint8! [10 25]] + +===end-group=== + ~~~end-file~~~ \ No newline at end of file From 7c84b60c8a2ba2cbd9c57fb416d87a563ad82713 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 12 Jan 2024 12:10:59 +0100 Subject: [PATCH 33/60] CHANGE: allow issues like `###` or `#a#` (Rebol2/Red compatibility) resolves: https://github.com/Oldes/Rebol-issues/issues/2583 --- src/core/l-scan.c | 1 + src/tests/units/lexer-test.r3 | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/core/l-scan.c b/src/core/l-scan.c index f67fba3028..5f3b9e9988 100644 --- a/src/core/l-scan.c +++ b/src/core/l-scan.c @@ -2149,6 +2149,7 @@ extern REBSER *Scan_Full_Block(SCAN_STATE *scan_state, REBYTE mode_char); || LEX_SPECIAL_PLUS == c || LEX_SPECIAL_MINUS == c || LEX_SPECIAL_TILDE == c + || LEX_SPECIAL_POUND == c )) return 0; diff --git a/src/tests/units/lexer-test.r3 b/src/tests/units/lexer-test.r3 index b3a789f1c9..a2b85a49d8 100644 --- a/src/tests/units/lexer-test.r3 +++ b/src/tests/units/lexer-test.r3 @@ -496,6 +496,16 @@ Rebol [ ===end-group=== +===start-group=== "Issue" + --test-- {###} + ;@@ https://github.com/Oldes/Rebol-issues/issues/2583 + --assert "###" = try [mold transcode/one {###}] + --assert "#a#" = try [mold transcode/one {#a#}] + --assert "#ab" = try [mold transcode/one {#ab}] + +===end-group=== + + ===start-group=== "Char" --test-- {#"^(1)"} --assert #"^A" = load {#"^(1)"} ;@@ https://github.com/Oldes/Rebol-issues/issues/52 From 52efc0caca758dfa9fc74256ee26757738c4c115 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sun, 21 Jan 2024 16:12:38 +0100 Subject: [PATCH 34/60] CHANGE: register `.swc` file extension with `zip` codec --- src/mezz/codec-zip.reb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mezz/codec-zip.reb b/src/mezz/codec-zip.reb index 612a40c757..e6926efa97 100644 --- a/src/mezz/codec-zip.reb +++ b/src/mezz/codec-zip.reb @@ -23,7 +23,7 @@ register-codec [ name: 'zip type: 'compression title: "ZIP File Format" - suffixes: [%.zip %.aar %.jar %.apk %.zipx %.appx %.epub %.docx] + suffixes: [%.zip %.aar %.jar %.apk %.zipx %.appx %.epub %.docx %.swc] decode: function [ {Decompress all content of the ZIP file} From fbad12f1a426e2802ac16898a88cff287270101b Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 25 Jan 2024 10:29:30 +0100 Subject: [PATCH 35/60] FIX: joining path/url using path notation not respecting index position resolves: https://github.com/Oldes/Rebol-issues/issues/2585 --- src/core/t-string.c | 10 ++++++---- src/tests/units/file-test.r3 | 14 +++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/core/t-string.c b/src/core/t-string.c index 25fcf6d2c9..a554b5287e 100644 --- a/src/core/t-string.c +++ b/src/core/t-string.c @@ -539,16 +539,18 @@ static struct { if (n > 0) c = GET_ANY_CHAR(ser, n-1); if (n == 0 || c != '/') Append_Byte(ser, '/'); - if (ANY_STR(pvs->select)) + if (ANY_STR(pvs->select)) { arg = VAL_SERIES(pvs->select); + n = VAL_INDEX(pvs->select); + } else { Reset_Mold(&mo); Mold_Value(&mo, pvs->select, 0); arg = mo.series; + n = 0; } - - c = GET_ANY_CHAR(arg, 0); - n = (c == '/' || c == '\\') ? 1 : 0; + c = GET_ANY_CHAR(arg, n); + n += (c == '/' || c == '\\') ? 1 : 0; Append_String(ser, arg, n, arg->tail-n); Set_Series(VAL_TYPE(pvs->value), pvs->store, ser); diff --git a/src/tests/units/file-test.r3 b/src/tests/units/file-test.r3 index 5ed2fcc6b1..58dd712374 100644 --- a/src/tests/units/file-test.r3 +++ b/src/tests/units/file-test.r3 @@ -26,7 +26,19 @@ secure [%/ allow] url: http://www.rebol.com page: %/test.html --assert url/test = http://www.rebol.com/test --assert url/:page = http://www.rebol.com/test.html - +--test-- "issue-2585" +;@@ https://github.com/Oldes/Rebol-issues/issues/2585 + url: http://www/ + dir: %path/ + file: next %a/bc ;== %/bc + --assert dir/:file = %path/bc + --assert url/:file = http://www/bc + file: next file ;== %bc + --assert dir/:file = %path/bc + --assert url/:file = http://www/bc + file: next file ;== %c + --assert dir/:file = %path/c + --assert url/:file = http://www/c ===end-group=== ===start-group=== "UN/DIRIZE" From 60e597f71380613d121ff919b22c8052e5f7f643 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 25 Jan 2024 10:39:26 +0100 Subject: [PATCH 36/60] TEST: https://github.com/Oldes/Rebol-issues/issues/2306 --- src/tests/units/file-test.r3 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tests/units/file-test.r3 b/src/tests/units/file-test.r3 index 58dd712374..5d2ff8a03e 100644 --- a/src/tests/units/file-test.r3 +++ b/src/tests/units/file-test.r3 @@ -20,7 +20,7 @@ secure [%/ allow] change-dir dir ===end-group=== -===start-group=== "concat url and file" +===start-group=== "concat url/file using path notation" --test-- "issue-1427" ;@@https://github.com/Oldes/Rebol-issues/issues/1427 url: http://www.rebol.com page: %/test.html @@ -39,6 +39,12 @@ secure [%/ allow] file: next file ;== %c --assert dir/:file = %path/c --assert url/:file = http://www/c +--test-- "concat with integer" +;@@ https://github.com/Oldes/Rebol-issues/issues/2306 + dir: %path + --assert dir/1 = %path/1 + --assert #"p" = pick dir 1 + ===end-group=== ===start-group=== "UN/DIRIZE" From 97a08a13ec55e437e030c8be5cd7f9de8aedcddf Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 25 Jan 2024 11:15:29 +0100 Subject: [PATCH 37/60] Build: disable Cirrus CI tests (not enough compute credits) --- .cirrus.yml => .cirrus.yml.disabled | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .cirrus.yml => .cirrus.yml.disabled (100%) diff --git a/.cirrus.yml b/.cirrus.yml.disabled similarity index 100% rename from .cirrus.yml rename to .cirrus.yml.disabled From da1905820e0091c4e27a7746e66f3ca5877a4ca7 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 26 Jan 2024 13:06:10 +0100 Subject: [PATCH 38/60] CHANGE: updated Mbed-TLS sources to version 3.5.2 --- NOTICE | 2 +- src/core/mbedtls/README.md | 2 +- src/core/mbedtls/rsa.c | 92 ++++++++++++++++++++------------ src/include/mbedtls/build_info.h | 8 +-- src/include/mbedtls/rsa.h | 9 ++++ src/include/psa/crypto_values.h | 7 +++ 6 files changed, 80 insertions(+), 40 deletions(-) diff --git a/NOTICE b/NOTICE index 4fcb6ec8ff..7d67d2d441 100644 --- a/NOTICE +++ b/NOTICE @@ -9,7 +9,7 @@ See included LICENSE file for details Credits for Non-REBOL orginated C files and modules --------------------------------------------------- -* MbedTLS parts (version 3.5.1): +* MbedTLS parts (version 3.5.2): Copyright The Mbed TLS Contributors Apache-2.0 - https://github.com/Mbed-TLS/mbedtls/releases diff --git a/src/core/mbedtls/README.md b/src/core/mbedtls/README.md index 924918f5cc..bf1c6bb658 100644 --- a/src/core/mbedtls/README.md +++ b/src/core/mbedtls/README.md @@ -1,2 +1,2 @@ In this directory is cherry-picked code from the Mbed TLS library. -Used version: 3.4.0 (https://github.com/Mbed-TLS/mbedtls/releases) +Used version: 3.5.2 (https://github.com/Mbed-TLS/mbedtls/releases) diff --git a/src/core/mbedtls/rsa.c b/src/core/mbedtls/rsa.c index db0b0f74f1..0ca0bfead4 100644 --- a/src/core/mbedtls/rsa.c +++ b/src/core/mbedtls/rsa.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" +#include "bignum_core.h" #include "rsa_alt_helpers.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" @@ -969,6 +970,45 @@ static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, return ret; } +/* + * Unblind + * T = T * Vf mod N + */ +static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); + const size_t nlimbs = N->n; + const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs); + mbedtls_mpi RR, M_T; + + mbedtls_mpi_init(&RR); + mbedtls_mpi_init(&M_T); + + MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); + + /* T = T * Vf mod N + * Reminder: montmul(A, B, N) = A * B * R^-1 mod N + * Usually both operands are multiplied by R mod N beforehand (by calling + * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka + * "in the Montgomery domain"). Here we only multiply one operand by R mod + * N, so the result is directly what we want - no need to call + * `from_mont_rep()` on it. */ + mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p); + mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p); + +cleanup: + + mbedtls_mpi_free(&RR); + mbedtls_mpi_free(&M_T); + + return ret; +} + /* * Exponent blinding supposed to prevent side-channel attacks using multiple * traces of measurements to recover the RSA key. The more collisions are there, @@ -1016,23 +1056,14 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, /* Temporaries holding the blinded exponents for * the mod p resp. mod q computation (if used). */ mbedtls_mpi DP_blind, DQ_blind; - - /* Pointers to actual exponents to be used - either the unblinded - * or the blinded ones, depending on the presence of a PRNG. */ - mbedtls_mpi *DP = &ctx->DP; - mbedtls_mpi *DQ = &ctx->DQ; #else /* Temporary holding the blinded exponent (if used). */ mbedtls_mpi D_blind; - - /* Pointer to actual exponent to be used - either the unblinded - * or the blinded one, depending on the presence of a PRNG. */ - mbedtls_mpi *D = &ctx->D; #endif /* MBEDTLS_RSA_NO_CRT */ /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ - mbedtls_mpi I, C; + mbedtls_mpi input_blinded, check_result_blinded; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; @@ -1067,8 +1098,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ); #endif - mbedtls_mpi_init(&I); - mbedtls_mpi_init(&C); + mbedtls_mpi_init(&input_blinded); + mbedtls_mpi_init(&check_result_blinded); /* End of MPI initialization */ @@ -1078,8 +1109,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, goto cleanup; } - MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T)); - /* * Blinding * T = T * Vi mod N @@ -1088,6 +1117,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); + /* * Exponent blinding */ @@ -1103,8 +1134,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); - - D = &D_blind; #else /* * DP_blind = ( P - 1 ) * R + DP @@ -1115,8 +1144,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, &ctx->DP)); - DP = &DP_blind; - /* * DQ_blind = ( Q - 1 ) * R + DQ */ @@ -1125,12 +1152,10 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, &ctx->DQ)); - - DQ = &DQ_blind; #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN)); #else /* * Faster decryption using the CRT @@ -1139,8 +1164,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, * TQ = input ^ dQ mod Q */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP)); - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); /* * T = (TP - TQ) * (Q^-1 mod P) mod P @@ -1156,21 +1181,20 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); #endif /* MBEDTLS_RSA_NO_CRT */ - /* - * Unblind - * T = T * Vf mod N - */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf)); - MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); - /* Verify the result to prevent glitching attacks. */ - MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E, + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E, &ctx->N, &ctx->RN)); - if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) { + if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); + olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); @@ -1198,8 +1222,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ); #endif - mbedtls_mpi_free(&C); - mbedtls_mpi_free(&I); + mbedtls_mpi_free(&check_result_blinded); + mbedtls_mpi_free(&input_blinded); if (ret != 0 && ret >= -0x007f) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret); diff --git a/src/include/mbedtls/build_info.h b/src/include/mbedtls/build_info.h index a9b9e27867..a936a025f3 100644 --- a/src/include/mbedtls/build_info.h +++ b/src/include/mbedtls/build_info.h @@ -26,16 +26,16 @@ */ #define MBEDTLS_VERSION_MAJOR 3 #define MBEDTLS_VERSION_MINOR 5 -#define MBEDTLS_VERSION_PATCH 1 +#define MBEDTLS_VERSION_PATCH 2 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x03050100 -#define MBEDTLS_VERSION_STRING "3.5.1" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.5.1" +#define MBEDTLS_VERSION_NUMBER 0x03050200 +#define MBEDTLS_VERSION_STRING "3.5.2" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.5.2" /* Macros for build-time platform detection */ diff --git a/src/include/mbedtls/rsa.h b/src/include/mbedtls/rsa.h index df665240d1..be831f19dc 100644 --- a/src/include/mbedtls/rsa.h +++ b/src/include/mbedtls/rsa.h @@ -684,6 +684,10 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 decryption * operation. * + * \warning When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15, + * mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an + * inherently dangerous function (CWE-242). + * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N (for example, * 128 Bytes if RSA-1024 is used) to be able to hold an @@ -720,6 +724,11 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * + * \warning This is an inherently dangerous function (CWE-242). Unless + * it is used in a side channel free and safe way (eg. + * implementing the TLS protocol as per 7.4.7.1 of RFC 5246), + * the calling code is vulnerable. + * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for example, * 128 Bytes if RSA-1024 is used, to be able to hold an diff --git a/src/include/psa/crypto_values.h b/src/include/psa/crypto_values.h index 5e33f6bd50..a17879b948 100644 --- a/src/include/psa/crypto_values.h +++ b/src/include/psa/crypto_values.h @@ -1736,6 +1736,13 @@ 0) /** RSA PKCS#1 v1.5 encryption. + * + * \warning Calling psa_asymmetric_decrypt() with this algorithm as a + * parameter is considered an inherently dangerous function + * (CWE-242). Unless it is used in a side channel free and safe + * way (eg. implementing the TLS protocol as per 7.4.7.1 of + * RFC 5246), the calling code is vulnerable. + * */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) From 592454e4090018accedbc4730dc79b7cc7320992 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 26 Jan 2024 22:33:54 +0100 Subject: [PATCH 39/60] FIX: LF to CRLF conversion when using `write` with `string` input resolves: https://github.com/Oldes/Rebol-issues/issues/2586 --- src/core/p-file.c | 3 +- src/core/s-unicode.c | 105 +++++++++++++++++++++++++---------- src/tests/units/port-test.r3 | 55 ++++++++++++++++++ 3 files changed, 134 insertions(+), 29 deletions(-) diff --git a/src/core/p-file.c b/src/core/p-file.c index ea21bacaa6..ced9c69915 100644 --- a/src/core/p-file.c +++ b/src/core/p-file.c @@ -340,7 +340,8 @@ REBINT Mode_Syms[] = { } else if (IS_STRING(data)) { // Auto convert string to UTF-8 - ser = Encode_UTF8_Value(data, len, ENCF_OS_CRLF); + // Using LF to CRLF conversion on Windows if not used /binary refinement! + ser = Encode_UTF8_Value(data, len, (args & AM_WRITE_BINARY) ? 0 : ENCF_OS_CRLF); file->data = ser? BIN_HEAD(ser) : VAL_BIN_DATA(data); // No encoding may be needed len = SERIES_TAIL(ser); } diff --git a/src/core/s-unicode.c b/src/core/s-unicode.c index ba9e6eb06e..07818d43eb 100644 --- a/src/core/s-unicode.c +++ b/src/core/s-unicode.c @@ -800,47 +800,96 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { REBINT n; REBYTE buf[8]; REBYTE *bs = dst; // save start - REBYTE *bp = (REBYTE*)src; - REBUNI *up = (REBUNI*)src; + REBYTE *bp; + REBUNI *up; REBLEN cnt; if (len) cnt = *len; - else { - if (uni) { + if (uni) { + up = (REBUNI*)src; + if (!len) { // not using wcslen, because on some systems wchar_t has 4 bytes! cnt = 0; while (*up++ != 0 && cnt < (REBLEN)max) cnt++; up = (REBUNI*)src; - } else - cnt = LEN_BYTES(bp); - } - - for (; max > 0 && cnt > 0; cnt--) { - c = uni ? *up++ : *bp++; - if (c < 0x80) { + } + for (; max > 0 && cnt > 0; cnt--) { + c = *up++; + if (c < 0x80) { #if defined(TO_WINDOWS) - if (ccr && c == LF) { - // If there's not room, don't try to output CRLF - if (2 > max) {up--; break;} - *dst++ = CR; + if (ccr) { + if (c == CR && up[0] == LF) { + *dst++ = CR; + *dst++ = LF; + up++; + cnt--; + max -= 2; + continue; + } + if (c == LF) { + // If there's not room, don't try to output CRLF + if (2 > max) { up--; break; } + *dst++ = CR; + max--; + c = LF; + } + } +#endif + *dst++ = (REBYTE)c; max--; - c = LF; } -#endif - *dst++ = (REBYTE)c; - max--; + else { + n = Encode_UTF8_Char(buf, c); + if (n > max) { up--; break; } + memcpy(dst, buf, n); + dst += n; + max -= n; + } } - else { - n = Encode_UTF8_Char(buf, c); - if (n > max) {up--; break;} - memcpy(dst, buf, n); - dst += n; - max -= n; + if (len) *len = dst - bs; + return up - (REBUNI*)src; + } + else { + bp = (REBYTE*)src; + if (!len) cnt = LEN_BYTES(bp); + for (; max > 0 && cnt > 0; cnt--) { + c = *bp++; + if (c < 0x80) { +#if defined(TO_WINDOWS) + if (ccr) { + if (c == CR && bp[0] == LF) { + *dst++ = CR; + *dst++ = LF; + bp++; + cnt--; + max -= 2; + continue; + } + if (c == LF) { + // If there's not room, don't try to output CRLF + if (2 > max) { bp--; break; } + *dst++ = CR; + max--; + c = LF; + } + } +#endif + *dst++ = (REBYTE)c; + max--; + } + else { + n = Encode_UTF8_Char(buf, c); + if (n > max) { bp--; break; } + memcpy(dst, buf, n); + dst += n; + max -= n; + } } + if (len) *len = dst - bs; + return bp - (REBYTE*)src; } - if (len) *len = dst - bs; - return uni ? up - (REBUNI*)src : bp - (REBYTE*)src; + } @@ -928,7 +977,7 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { else { REBYTE *bp = (REBYTE*)src; - if (Is_Not_ASCII(bp, len)) { + if (ccr || Is_Not_ASCII(bp, len)) { size = Length_As_UTF8((REBUNI*)bp, len, FALSE, (REBOOL)ccr); cp = Reset_Buffer(ser, size + (GET_FLAG(opts, ENC_OPT_BOM) ? 3 : 0)); Encode_UTF8(cp, size, bp, &len, FALSE, ccr); diff --git a/src/tests/units/port-test.r3 b/src/tests/units/port-test.r3 index 59ae60884b..5c67148111 100644 --- a/src/tests/units/port-test.r3 +++ b/src/tests/units/port-test.r3 @@ -276,6 +276,61 @@ if system/platform = 'Windows [ --assert "a^/b^/c" = read/string %units/files/issue-622.txt delete %units/files/issue-622.txt + --test-- "read write CRLF conversion" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2586 + ;; In these tests are used #"a" and #"á" to have internally plain and wide strings + ;; write/binary keeps the linefeeds without modifications + --assert #{0A} = read write/binary %tmp next "a^/" + --assert #{0A} = read write/binary %tmp next "á^/" + --assert #{0D0A} = read write/binary %tmp next "a^M^/" + --assert #{0D0A} = read write/binary %tmp next "á^M^/" + --assert #{0D0D0A} = read write/binary %tmp next "a^M^M^/" + --assert #{0D0D0A} = read write/binary %tmp next "á^M^M^/" + --assert #{0D0A0A} = read write/binary %tmp next "a^M^/^/" + --assert #{0D0A0A} = read write/binary %tmp next "á^M^/^/" + ;; it is possible to get the original string using implicit conversion + --assert "a^/" = to string! read write/binary %tmp "a^/" + --assert "á^/" = to string! read write/binary %tmp "á^/" + --assert "a^M^/" = to string! read write/binary %tmp "a^M^/" + --assert "á^M^/" = to string! read write/binary %tmp "á^M^/" + --assert "a^M^M^/" = to string! read write/binary %tmp "a^M^M^/" + --assert "á^M^M^/" = to string! read write/binary %tmp "á^M^M^/" + --assert "a^M^/^/" = to string! read write/binary %tmp "a^M^/^/" + --assert "á^M^/^/" = to string! read write/binary %tmp "á^M^/^/" + either system/platform = 'Windows [ + ;; on Windows by default write converts LF to CRLF (if the input is string!) + --assert #{0D0A} = read write %tmp next "a^/" + --assert #{0D0A} = read write %tmp next "á^/" + ;; when there is already CRLF, if does not write it like CRCRLF! + --assert #{0D0A} = read write %tmp next "a^M^/" + --assert #{0D0A} = read write %tmp next "á^M^/" + --assert #{0D0D0A} = read write %tmp next "a^M^M^/" + --assert #{0D0D0A} = read write %tmp next "á^M^M^/" + --assert #{0D0A0D0A} = read write %tmp next "a^M^/^/" + --assert #{0D0A0D0A} = read write %tmp next "á^M^/^/" + ][ + ;; on all other platforms it does no modifications! + --assert #{0A} = read write %tmp next "a^/" + --assert #{0A} = read write %tmp next "á^/" + --assert #{0D0A} = read write %tmp next "a^M^/" + --assert #{0D0A} = read write %tmp next "á^M^/" + --assert #{0D0D0A} = read write %tmp next "a^M^M^/" + --assert #{0D0D0A} = read write %tmp next "á^M^M^/" + --assert #{0D0A0A} = read write %tmp next "a^M^/^/" + --assert #{0D0A0A} = read write %tmp next "á^M^/^/" + ] + ;; read/string converts CRLF (or plain CR) to LF + --assert "^/" = read/string write/binary %tmp next "a^/" + --assert "^/" = read/string write/binary %tmp next "á^/" + --assert "^/" = read/string write/binary %tmp next "a^M" + --assert "^/" = read/string write/binary %tmp next "á^M" + --assert "^/" = read/string write/binary %tmp next "a^M^/" + --assert "^/" = read/string write/binary %tmp next "á^M^/" + --assert "^/^/" = read/string write/binary %tmp next "a^M^M^/" + --assert "^/^/" = read/string write/binary %tmp next "á^M^M^/" + --assert "^/^/" = read/string write/binary %tmp next "a^M^/^/" + --assert "^/^/" = read/string write/binary %tmp next "á^M^/^/" + --test-- "write file result - wish/2337" ;@@ https://github.com/Oldes/Rebol-issues/issues/2337 From 1c73cfe7181740cdc499d8228a29b99d5e9bef79 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 26 Jan 2024 22:45:11 +0100 Subject: [PATCH 40/60] Fixed comments --- src/tests/units/port-test.r3 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/units/port-test.r3 b/src/tests/units/port-test.r3 index 5c67148111..d8b9f4d7c3 100644 --- a/src/tests/units/port-test.r3 +++ b/src/tests/units/port-test.r3 @@ -298,10 +298,10 @@ if system/platform = 'Windows [ --assert "a^M^/^/" = to string! read write/binary %tmp "a^M^/^/" --assert "á^M^/^/" = to string! read write/binary %tmp "á^M^/^/" either system/platform = 'Windows [ - ;; on Windows by default write converts LF to CRLF (if the input is string!) + ;; on Windows `write` converts LF to CRLF by default (if the input is string!) --assert #{0D0A} = read write %tmp next "a^/" --assert #{0D0A} = read write %tmp next "á^/" - ;; when there is already CRLF, if does not write it like CRCRLF! + ;; when there is already CRLF, it does not write it like CRCRLF! --assert #{0D0A} = read write %tmp next "a^M^/" --assert #{0D0A} = read write %tmp next "á^M^/" --assert #{0D0D0A} = read write %tmp next "a^M^M^/" @@ -309,7 +309,7 @@ if system/platform = 'Windows [ --assert #{0D0A0D0A} = read write %tmp next "a^M^/^/" --assert #{0D0A0D0A} = read write %tmp next "á^M^/^/" ][ - ;; on all other platforms it does no modifications! + ;; on all other platforms it doesn't modify! --assert #{0A} = read write %tmp next "a^/" --assert #{0A} = read write %tmp next "á^/" --assert #{0D0A} = read write %tmp next "a^M^/" From 307b24a9012fdbb37d1d3e29031e7e96ca7dca2d Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Mon, 29 Jan 2024 12:17:18 +0100 Subject: [PATCH 41/60] FIX: Windows JPEG codec unexpected property type error resolves: https://github.com/Oldes/Rebol-issues/issues/2587 --- src/os/win32/sys-codecs.cpp | 4 ++-- src/tests/units/files/issue-2587.jpg | Bin 0 -> 9834 bytes src/tests/units/image-test.r3 | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/tests/units/files/issue-2587.jpg diff --git a/src/os/win32/sys-codecs.cpp b/src/os/win32/sys-codecs.cpp index 376309b98b..815d17fefb 100644 --- a/src/os/win32/sys-codecs.cpp +++ b/src/os/win32/sys-codecs.cpp @@ -80,7 +80,7 @@ CODECS_API int DecodeImageFromFile(PCWSTR *uri, UINT frame, REBCDI *codi) (LPCWSTR)uri , NULL , GENERIC_READ - , WICDecodeMetadataCacheOnLoad + , WICDecodeMetadataCacheOnDemand , &pDecoder ); ASSERT_HR("CreateDecoderFromFilename"); @@ -110,7 +110,7 @@ CODECS_API int DecodeImageFromFile(PCWSTR *uri, UINT frame, REBCDI *codi) hr = pIWICFactory->CreateDecoderFromStream( pStream , NULL - , WICDecodeMetadataCacheOnLoad + , WICDecodeMetadataCacheOnDemand , &pDecoder ); ASSERT_HR("CreateDecoderFromStream"); diff --git a/src/tests/units/files/issue-2587.jpg b/src/tests/units/files/issue-2587.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94f08b9c598bd3f57fb7d51a20761e536e6718cd GIT binary patch literal 9834 zcmbW7WmH^Gx8@rfXxt$<1b266B)A6;5`qTT#@z`Cu7TjzNPyr@@J52W28V{=Gywu( z_`mPHbMMTDSu?YH?N$4n+Fhrfs|prN3mp`xInp`w96 zXy};un3xzCn8dhv*!VAq$;e(1laf+UGtp8|GEk9{(s9x;Ftf0+vyszs@p7^9GO@C; z{?iB&2n51J$0WkUBx0o?rC|Mkwx=Ed0Xm=n;08pZ2Otw50SSE}DV`OY) zZS&sN&fWpy>E-R?>*pU485JG#A@*ZRYFc_m=I5;JqT-U$GH7{4Wqm_qQ*%peTYF#s zz~B&Ucw}^Dc5Z%QacOyFYkOyRZ~x#Bespnpb&a_BeS3HRk1nL=Y5Pz6x3K?B7s0bG zWE2!23g{nQNXS0V4kSQ9eaVMLD60*!a3`YY4?`z@m0VcYi@_kEb53IEF^x&eD7eLR z@sG5BDf_<@7XJUG?0*XTFI_7DY#`F}TYm zyu<;MQxQf|QBnC%0n3YlGjVvT0M-Ie;@3#Bhjsoe$2aR=5UGliBEM#$vX^VhOcE^e)`acRZrWy;3{;|o&L;?IP-rDf>+x(4beOA z&}gIb^2H&8H2YbAO#mCSqkFI1>fEIS`|XY|BOi)(aGDY&KJ?t-v9yisB<(F+mzR9* zJ3YZ1{Yom_cW0v(m;40Kc(FR$i)X+<2 z3DzprdWhrnn6Qd1HI7S`5-dBy0JRw(~o?yC{D`8E5bSGsbKJFAW zsch_T&#)S812VLKcRVVpz;-^~ai%Lkbs!y@3yWuq4+(2btaI7UhGL{g~7kNn_2^Z$Mu{4!w1YQ!a<-CapS>jv>+M#t8Y@$di#aTo;nmY{sdrR!xR z9bs7l9y)T2qy&8O9q(1(CXi#^)$u6Vy#$d{14iKQ94V6a_EP4KU^esVT8?-z_lKN+ znJ*%VI1T*EYI$?hEokjmRKKC*d}D|R#T7@^(l$%n8n-f@6Fh`|pJO&keHqm?mjBrr zlGhmwsx5`o8=D*{hBS}XzZoKBe4H4;$B%FQ_8ZhD3U=6Q`XMY_bE7kKQ{&Tls?rNP zKldRT65CuHux;)3`$Hw(SoB+U1z|XK#oBAsmPS3+*E3oPOtM$~}KbxE%1WXp0$ za4znLHmng35zi?JV5cfY0_qK;16r_td_!huwpf|FW21R^2@3$S86%S3rtca$>zNY z@5G7+zPI@2%$0d6Cd$G+KP=^w^?0;XZ;4FjC*x`xKNQw~F`DP$&Q*_=*{ly+I|rD7 zB?tquTP1D%ofni5v5XOoBcjRru=h5M=5dI>Mcrma{f1`CGZn1g+wLBo05!0r9igha z7U?iV^XphDBqWyIB<#GVS6WEE+1@nfVHl#E);M8rTDpZ6%etFBX>_$EpH7h#*$cbR z<>W!hML`b^um{HWy|izuV>Mb3?;T%-(Kt`AiRfgYx6tX{HS1LA3$mslrxUN=^!8OP zKDCqA!mzMTIaj-v(V~ntlF~WEIefkMn+I1UYjRKr=YkL1Ryclpk**uKS~ZR%T!A*V z8lD()HP&%`7_3X$DOyffad>_0CvpRZZp+49-KCzZy&Gf?JrRp=vnJ8TMkQ1)5+2{{ z6Dj8Kz7-ZSyKQ|2v0eaXUL~Aguw6ebVK8?~krBaIzF+;?sTmXcHOiUhR*bz21Bs!W zQp2>ey-`Q2)NBxd!DPwEf{{oy}-Y$b32775v&K*f}nMVq(Ub;d~=b z=kiFcjIN`joD&AH0zi6bn&ww;l?e#m!2K!FZ`OiPEdL~}sqPy#KA4(RAWXR`ITO31t-GU3Ou@_CA0GNwIMDQccl;+C} z_EDSIeCh-_b2qK;2ia}3eL?SUrYUwbGgf?;1hob0>bda>Tp$UuEMi9-M>~=6WaZEw z8H-?35>+g}`yat`mEtp%Oveh(m7m%jmo>(Jw(w%D zq8*(n)?{tnLi~v1DV?7HUJV`1eE0Jc+AKk`-#GB4S>SO}};w_gwKS1+Ew`!vx)6qKt0&6pnEF&~!73cNS)fCOQ)Z+%Of zuh9Es4|ee&U|Nq`Byf#ZnNdi-Aq??^q$aeD=Ks)}-WaPg9^w3H7Yzqx@e zw1ZiC&Dd$^v;Xd>@b=v7kw{)kP`V9CS>wG~5Y% zv`2`sP*&v+%ZS^M-9`b|o8BcL1+FZWxvq z31JUw{iRtF#F2j?65DA=1yQl71h*^V8gcEIi$gNZe(o42RVnVi;wR%aAwTqk!}Sm% z>?rIXZ)S1?QbS)n_b4BtfGt^6%Tm31+}s`n1B*Y@>U%x`s&PsFGTja_hhxRtTPkr% z-b536d;QGqP?R#ohNL2Dj$d6UeV|oVJMJ=2vGnqY+KR_Y5Y9o}k=!}26^i*Ko>v36 zvCe!y3L!IaBRLnbb#ZfZUrmre95QwXS#F3GcKzXec_aTS==uH7@q1Tm*2T`Jv96d6 zc9L$`*D0T~m~XoC5)a5HKQ3>5D^ua--I7U88$&hE)=hV;+!JE&hCb$}a_4z(D6vhR zsquF9v2@#p)7pAsNFU{DYS%gxugNXD<1yCfnA12Q62p<$1K+~HH7!Xz$NaY>KB{V_ z_;lVApsA76IL~Ee)E-X54sa0rO2-t6|qpuh*Cw|7P+d21aqo**rMgORu<{eC82gki`loS=WPj#Q^BMw&64uR>OwR44b2(JR z;*M<-_@mCMFK&|r)Ix?RyDf%EG0k4Lx||?lp8&qT$mofZ?xXi}v=%Kf>OOT|?i8rz zygt^+NnkM`G1va8#3zXl^^xp-?n#mU2q1%`p+D5lq~bE&;YwpvoMG*O!%OIQv|vC- zk;dR)4*#$+Aj2AE7Z=3b#2ynfv<}js$(Y7_@YKKGw|%w5UQ+`b8?1Nd2*am zf~{W}eXr|k{yQIxumN}kh@Y_Yo!ob%HrHk1cH%BWb zVnvTXk_QSfUPwfT&`VPsI(QiHLeW>VJb4>K(0(3@)ORJu2pKIHyxFlQiJo)K8rwun zfPf%sKT)S{$_wikICSUhb8rUYSc34c?%}P&WWaQWLdIY(=I+g5$k+|4yzO6gv}=U9|+~g(J)ET zXHbjpPvEcv^!Kt!#zajwZQCS~5G-M)I=en`CaOQ+eSM`A$-i|QW}X1&c;cUWXha+N z*G9G^^2K`lm0YNr6@^*d~-K5R-TVgS=2r*X*^@hXtM8Ww?<$j)n9LI^_J?E z-c+o~scdTibqb757U2IQe8VdMFevDeq(nAIHng z*pW^9HqC8wp-otB0kk~6**9!L7@hqBohU<3ANUYiym(dmrXGsfRBNiH@K*Nwbyv}QV#uF zYuL2p_Wty;v5cakqSy%4RSykfX}`G2ypUWj11wFMIK`=Pm_ljvaV4VN=&FM;0R)wF zlkoQxqX;*$_c^n5tyG*IzI&5a@8r@3j4!zwQWh$%TDk2W?W5)r1S?9oMZTX|QITUM z+uejL;R@U>aQN!#N2tF5_TQJJsHN_GdBKf-NQRVy=ta3EF8vT^th1aghrQ>sRFkS= z6_xVWyH%od5m!0>Rf9RCp9<+V-(fNw>yvy_N0UdU2O2L&0T2Gj2txsjq?PCpxNptZ zYM?#6f&Y+Vm(fM$yQP;j-%cDP&P!@-zgd!c%as6zQtv=vR-f97&r8~vO6RiYp77l_ z&VAg?(4okggQl6_5BpT2aPH6RYtiHCm$fyhB{#D&RCmEvE;?O*oi0{|YRIohN)Iym z+mqd<5z=f(Z7dS*IX={4gI?Kr5!+m^&;qpZ-VLZL2!K1Np8(wah7H*MkmKVCjV)Jv z#tMns5JPt42HLt|>fxam04fgwn5?O%UqwjSH3dLkRpb4=kV1Eh}z*ves%`W9-2Clv??_oAvV_h z)||>O;na{M4RG0UMakV*`!hFXbXzH6|Dt~-)tKY&>3a44n!gKOl6w+}(fU61txgpy z;!k3Jl<3^Fg7ovwF8la6gyCost)V4SP&j>T*vXs|cAJ>dCRAr6MSv^GRuucvj><^3 zorR1qpUb1f+&m!{)zP3zcQU2Hjup&Wa4m?QU|$?VW92;IKB(yW5`?BX@HjhVD?L2_ z@uMFp$(q%BGR7nj8To!FS*BYDui?a$is(+9?cHqfx@)-lXJDQz941{}@D}%69arX0 z-uIcbb-MWV!ZhdAUQJDZ%TP+82Lc7bxbb?{AMs%mXppd5y>}}MZL@zp41P=Lx`#z^ zLM96yjzSu7m6Eyn9w%#WgBzpW7=~L?W0qdHN*%yu2ox#?nW5m6lCUk5&KQ>sWGb&o zCEeMD;DoV ze*bKCu1mi|t&?*JK)#-HPji9AXDr7Xh$z6mxzJ4On6DvIFJ|V7@wp8^z{l)@&E30_fWs#zl?nr17AxtM7Dndz3AbU(mYMO!AXhP)9ce;gedgz+|yMjRgD_j9s zP!x)ZC#OJ+G&$zC4Oo=YkLqC0lKh$^V)0k~;c+qNJ}-i*%T=hW{e!SuMlA749w7Z= zT)0S%`F@LC0j@u_oSA)rkzk`d4{i49+=&kF?Ol5~#y!Cr#Y%>XVm}2ivp;~R);RAY zppu&#eSaSHdvH49fcShJFT-#e+r>#twQ zicA@kZUw>Q5FMJ*dS`5x?Yv1DjL|Cr1A-j}|HXw^3-F$n|HYFrK_GMx8YVhAIu<4- z7A_e+E)EVZH3=yJ83Qd7BRwtsOJ)uc9%eQ{wwLt0vV4MK5>ir9Ox*G+a+1m-U@3`z z@nlRaELnaMb1U zqE5QX+L zBsxtYXB7)(uPL52dQFH2yiY3t3Ti6=yg#xQAh$X;ZL1Knjty@SdoiA~Q>wfTJ1st~ zJ#{`^5v)&nGcV%u+QZihmiZb@{I){3@(s^;06KiW=XfSL)ojM%3GidCTK5T%7OHQh zL%3X~@ueq!+lODB#B|Tz+bx^p}hc&LV@~tvq_I6^s~%x|Bxo5#uhBz2gS{|TEy9&rG)zO)^gjR zD%+{&BLdZ8$(+rPm)CcCdD?vz@=7&!r6bA;F|sH2 zIX?6|^H8FZ)98E7E`f-(6_inxjzgOh-GI)bG%xptD=-rm-8@Z_Ao0Zo$HOHK!SYW4 zyc^^&h$QJ5vv!X9-Duzjt@PZypG}IjkaM4{rvNVK;|Da|t1@GE|iUDIP7 zaoXHDo}1GzU2a{aE-f&zMCaadfHn(Eiow<7GZ`~J3fWk?%_L$E-0t83fJr8{E&mmW0lU38Pja%w-Z*H-X$;C4@E!^qk+>=>XXp^TFRmf-Su|y|Z zxJvB8-p#8XQS$Y?oWIwP!U{z&-$<@X?RfNNc1z92UUW(#J)(RTp z=Urv%Et?eMw-}(i=|OFiSox#xx9J*TU1kP!rVkHL4F}iOYANrD;V}413X>lDiPl*oQ6CtpHsB=2ZR(`EqYZ z5lp?OI|JjXn%aA*Ee92D(Nd$Uip^CQ)NAI>I2-r?_;`Tpo{gbB_L5mgTnuofA#!2A zF^#k3+n5;4KUKn+Trv`-j`yxfvSZ#VrcR?;0IP2@4k>j`sRTcWq=~pI$tk`RtIo21G41Ww&MfX&PsZ8Q?&+Uwza`Wp|D8|d= zSq3yO1%6jJbDhx4H6>e-LvoiVd=X#of9fg=?qI5#NhBtD;Y7@Zv>Y4!9a5h?j9R9~ z$Z8GlLbY?R=k47vA-dL9&~wxC{>~v+WI7z0@fscYW7l0raOLlt!uk}Ioiheg7gMkO zB2{=1%^=~raLo_vxYV!&6_&)dat&95bQg*8F-C_CX1s> z$&J8!VKZf#(88}W%?ZTTp`}D)XKz_hNmF`fW*wMb*ihaGn4I9APF(O*PqP@raV95k z1Ib1=6S;GC^-NPMe})kgt<#YKQTYeLJ$Qovm+-J54kPhN+pCuIz&Km*ih1yL>P39BBpSsEG^fWFsQ*FTV?smPd+aB6#JgACbBs0g2LLU@i;hEK; z%EF`y8;Rz-6fMys0fU7_3GtgA9Q@(Lzo8#wA1^e%f0keaugcw`d&jY#@-a)fMC2QP z=>GztsW;W`h|t^%RwLu&Q6FQT$3(&nWCc-$Od5CG;O9=`}Q5}T+fv9tP zxlDAroGoAR*Xmel9R(dZ)@QD`6qZW1>u2`%H1Lx(mtUA$-)c$@+NXMpepCI;d|33c zV5&^K?{o$VoC;}$&ePU#2q%kbbaaYt@Jm_fv~X}`nS3xOtIOc@gK0(=37G`gZ?cy# zCf)9eU0#hy=`#rRtr~wzpBhC|VaY9?Ow?^zD6HjHY+Ei%AxF)bMUGYqMC~_Ez{}%9 z2o4VkZl^3`lobQK7Q=dkr0A~9Z#+*E#%ST$jEm5jS;@x7Fh6$K@P zz;7zWxY~1-kD&U^-%>`b8r!3(1-3VK*rK!v<-%3K0GMh1(p+@11-MUe5<8jGBjv+M z3XF^;Q9Z{W^07S2nd#M!9Zz||N=-TUF)Az2{hi-@v21t728WkD`3}dOK-EF#^Xe8& z734q5CN%ioVop&uV0;J-$v1BH#+{(#LQ^i#AztgC%6UF~ z{?UJ1{h`_3_B7#uoycts;SbZpG}kdD(YEB@;IWed9&qPAMK3b6HR zPz^OT88&P?6LsZ!5svx+UQ*HD$2^RH-9iLe*FcNt>9M3hcltI47ZyAuO275 z6bmwo;}o$!`Z{1H?yp#|wN-h*k_T}cO+d`|)#_)Kw*UIu5e@6Gq3Qb!l)qz!=W8i}T(Ma*x`B10HyMgQHi5~{0p`BH+^z7%xakYN z`Ra$c+NY_*~p}AIhqZDoaDSN(b7>#x$>i2 zHW8AxsP#ktS%Fx=FPY~R$fC43;j$x$gHlpbV?_FjhBMUccTzrq@B|Q;v%^s4KIqE- z_Nzgkj}j15^&+`7?9smd*n54A8_thWyiqWuLbZc}8(k>N;^E-1C(0_+QjySc6K$*0 z9(2Kkp4LfN={z|~jGHSSbY*OKe)awDyQH<{F?*hY=G`=WlfLekc?EOp&9%;6`~$h$ z4TLW|2y$$%;Rjk#Mv4=^3D{$Y77!8&#QIUFZi|jFP-3JNRi$JTESjz3?8J|Y2AJV$ z^G*aE01wF_@5ie|SO25ls;|5e5b|^;u9skHz8*O2;r=!7^u{!CSo$|6cD)-4r^;(B zFkY!peT+{0>h>u^dO(x@3g0%h2{hkSw~Xk_@@t36Cc%_tDDI`1G$Vp07_qNntCwj_ z&i++5|8p4Z_$@6_g0b|}^rtwFv7AJP*@;km5s{xDfltyCN-r7Kueg21?sek1raR*a z3D(R>A&ZZuUN`R+y22n&0G;6IF4jz-ANgd`WdSN{iJmFaSjE8)Kb?vWyY;xc?NG3` N0x{tK;7Cu){{s=BJ~{vZ literal 0 HcmV?d00001 diff --git a/src/tests/units/image-test.r3 b/src/tests/units/image-test.r3 index 8fbf2f4f27..1bc57a49a4 100644 --- a/src/tests/units/image-test.r3 +++ b/src/tests/units/image-test.r3 @@ -488,6 +488,15 @@ if value? 'blur [ #{0A00000A0A00000A0A00000A0A00000A} ;; premultiplied on macOS :/ ] to binary! img2 ] + + if find codecs 'jpeg [ + --test-- "loading JPEG file with an unexpected property type" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2587 + --assert all [ + img: image? try [load %units/files/issue-2587.jpg] ;; no error! + img/size = 105x150 + ] + ] ===end-group=== ===start-group=== "Image as a series" From 1bfcbbcf83827b846ef7f3fa508bd1afc0796de6 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Mon, 29 Jan 2024 15:29:29 +0100 Subject: [PATCH 42/60] FIX: bbcode codec - reset row-width of an image gallery tag --- src/mezz/codec-bbcode.reb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index 4b285a5c29..206de4e0db 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -2,7 +2,7 @@ REBOL [ Name: bbcode Type: module Options: [delay] - Version: 0.3.3 + Version: 0.3.4 Title: "Codec: BBcode" Purpose: {Basic BBCode implementation. For more info about BBCode check http://en.wikipedia.org/wiki/BBCode} File: https://raw.githubusercontent.com/Oldes/Rebol3/master/src/mezz/codec-bbcode.reb @@ -267,7 +267,7 @@ emit-tag-images: function/with [][ alt: get-attribute/default "alt" "" unless empty? alt [insert alt SP] - columns: num: 0 + row-width: columns: num: 0 temp: clear [] files: none dir: to-rebol-file get-attribute "dir" From 4ee7767a1b4a14f02ae88d8b3282c15edf4fcf0d Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Tue, 30 Jan 2024 18:56:41 +0100 Subject: [PATCH 43/60] Build: support of RISC-V architecture related to: https://github.com/Oldes/Rebol-issues/issues/2584 --- make/rebol3.nest | 300 ++++++++++++++++++++++++++++------------------- 1 file changed, 179 insertions(+), 121 deletions(-) diff --git a/make/rebol3.nest b/make/rebol3.nest index c72775a00f..cce52dd52b 100644 --- a/make/rebol3.nest +++ b/make/rebol3.nest @@ -131,6 +131,14 @@ target-turris: [ :arch-x64 arch: arm64 ] + cross-linux-riscv64: [ + ;- requires: sudo apt-get install gcc-riscv64-linux-gnu + compiler: %/usr/bin/riscv64-linux-gnu-gcc + library: %/usr/riscv64-linux-gnu/lib/ + :target-linux + :arch-x64 + arch: riscv64 + ] ] core-files: [ @@ -1092,6 +1100,10 @@ arch-mips64le: [ :common-64bit arch: mips64le ] +arch-riscv64: [ + :common-64bit + arch: riscv64 +] ;------------------------------------------------------------------------------- @@ -1142,6 +1154,7 @@ make-armv6-exe: [:arch-armv6 :make-exe ] make-armv7-exe: [:arch-armv7 :make-exe ] make-arm64-exe: [:arch-arm64 :make-exe ] make-mips64le-exe: [:arch-mips64le :make-exe ] +make-riscv64-exe: [:arch-riscv64 :make-exe ] ; for making Rebol as a shared library make-dll: [ @@ -1277,127 +1290,154 @@ eggs: [ ] ] #if Linux? [ - "Rebol/Base linux-x86" [ - name: %rebol3-base-linux-x86 - :target-linux - :make-x86-exe - ] - "Rebol/Core linux-x86" [ - name: %rebol3-core-linux-x86 - :target-linux - :include-rebol-core - :make-x86-exe - ] - "Rebol/Bulk linux-x86" [ - name: %rebol3-bulk-linux-x86 - :target-linux - :include-rebol-bulk - :make-x86-exe - ] - - "Rebol/Base linux-x64" [ - name: %rebol3-base-linux-x64 - :target-linux - :make-x64-exe - ] - "Rebol/Core linux-x64" [ - name: %rebol3-core-linux-x64 - :target-linux - :include-rebol-core - :make-x64-exe - ] - "Rebol/Bulk linux-x64" [ - name: %rebol3-bulk-linux-x64 - :target-linux - :include-rebol-bulk - :make-x64-exe - ] - - "Rebol/Base linux-armv6" [ - name: %rebol3-base-linux-armv6 - :target-linux - :make-armv6-exe - ] - "Rebol/Core linux-armv6" [ - name: %rebol3-core-linux-armv6 - :target-linux - :include-rebol-core - :make-armv6-exe - ] - "Rebol/Bulk linux-armv6" [ - name: %rebol3-bulk-linux-armv6 - :target-linux - :include-rebol-bulk - :make-armv6-exe - ] - - "Rebol/Base linux-armv7" [ - name: %rebol3-base-linux-armv7 - :target-linux - :make-armv7-exe - ] - "Rebol/Core linux-armv7" [ - name: %rebol3-core-linux-armv7 - :target-linux - :include-rebol-core - :make-armv7-exe - ] - "Rebol/Bulk linux-armv7" [ - name: %rebol3-bulk-linux-armv7 - :target-linux - :include-rebol-bulk - :make-armv7-exe - ] - - "Rebol/Base linux-arm64" [ - name: %rebol3-base-linux-arm64 - :target-linux - :make-arm64-exe - ] - "Rebol/Core linux-arm64" [ - name: %rebol3-core-linux-arm64 - :target-linux - :include-rebol-core - :make-arm64-exe - ] - "Rebol/Bulk linux-arm64" [ - name: %rebol3-bulk-linux-arm64 - :target-linux - :include-rebol-bulk - :make-arm64-exe - ] - - "Rebol/Base linux-mips64le" [ - name: %rebol3-base-linux-mips64le - :target-linux - :make-mips64le-exe - ] - "Rebol/Core linux-mips64le" [ - name: %rebol3-core-linux-mips64le - :target-linux - :include-rebol-core - :make-mips64le-exe - ] - "Rebol/Bulk linux-mips64le" [ - name: %rebol3-bulk-linux-mips64le - :target-linux - :include-rebol-bulk - :make-mips64le-exe - ] - - "Rebol/Core linux-x64 shared library" [ - name: %librebol3-core-linux-x64 - ;lflag: "-Wl,-install_name,'/usr/local/lib/librebol-core.3.so'" - :target-linux - :include-rebol-core - :make-x64-dll - ] - "Rebol/Core linux-x64 host application" [ - name: %host-core-linux-x64 - shared: %librebol3-core-linux-x64 - :target-linux - :include-rebol-core - :make-x64-host + #if (system/build/arch = 'x86) [ + "Rebol/Base linux-x86" [ + name: %rebol3-base-linux-x86 + :target-linux + :make-x86-exe + ] + "Rebol/Core linux-x86" [ + name: %rebol3-core-linux-x86 + :target-linux + :include-rebol-core + :make-x86-exe + ] + "Rebol/Bulk linux-x86" [ + name: %rebol3-bulk-linux-x86 + :target-linux + :include-rebol-bulk + :make-x86-exe + ] + ] + #if (system/build/arch = 'x64) [ + "Rebol/Base linux-x64" [ + name: %rebol3-base-linux-x64 + :target-linux + :make-x64-exe + ] + "Rebol/Core linux-x64" [ + name: %rebol3-core-linux-x64 + :target-linux + :include-rebol-core + :make-x64-exe + ] + "Rebol/Bulk linux-x64" [ + name: %rebol3-bulk-linux-x64 + :target-linux + :include-rebol-bulk + :make-x64-exe + ] + ] + #if (system/build/arch = 'armv6) [ + "Rebol/Base linux-armv6" [ + name: %rebol3-base-linux-armv6 + :target-linux + :make-armv6-exe + ] + "Rebol/Core linux-armv6" [ + name: %rebol3-core-linux-armv6 + :target-linux + :include-rebol-core + :make-armv6-exe + ] + "Rebol/Bulk linux-armv6" [ + name: %rebol3-bulk-linux-armv6 + :target-linux + :include-rebol-bulk + :make-armv6-exe + ] + ] + #if (system/build/arch = 'armv7) [ + "Rebol/Base linux-armv7" [ + name: %rebol3-base-linux-armv7 + :target-linux + :make-armv7-exe + ] + "Rebol/Core linux-armv7" [ + name: %rebol3-core-linux-armv7 + :target-linux + :include-rebol-core + :make-armv7-exe + ] + "Rebol/Bulk linux-armv7" [ + name: %rebol3-bulk-linux-armv7 + :target-linux + :include-rebol-bulk + :make-armv7-exe + ] + ] + #if (system/build/arch = 'arm64) [ + "Rebol/Base linux-arm64" [ + name: %rebol3-base-linux-arm64 + :target-linux + :make-arm64-exe + ] + "Rebol/Core linux-arm64" [ + name: %rebol3-core-linux-arm64 + :target-linux + :include-rebol-core + :make-arm64-exe + ] + "Rebol/Bulk linux-arm64" [ + name: %rebol3-bulk-linux-arm64 + :target-linux + :include-rebol-bulk + :make-arm64-exe + ] + ] + #if (system/build/arch = 'mips64le) [ + "Rebol/Base linux-mips64le" [ + name: %rebol3-base-linux-mips64le + :target-linux + :make-mips64le-exe + ] + "Rebol/Core linux-mips64le" [ + name: %rebol3-core-linux-mips64le + :target-linux + :include-rebol-core + :make-mips64le-exe + ] + "Rebol/Bulk linux-mips64le" [ + name: %rebol3-bulk-linux-mips64le + :target-linux + :include-rebol-bulk + :make-mips64le-exe + ] + ] + #if (system/build/arch = 'riscv64) [ + "Rebol/Base linux-riscv64" [ + name: %rebol3-base-linux-riscv64 + :target-linux + :make-riscv64-exe + ] + "Rebol/Core linux-riscv64" [ + name: %rebol3-core-linux-riscv64 + :target-linux + :include-rebol-core + :make-riscv64-exe + ] + "Rebol/Bulk linux-riscv64" [ + name: %rebol3-bulk-linux-riscv64 + :target-linux + :include-rebol-bulk + :make-riscv64-exe + ] + ] + #if (system/build/arch = 'x64) [ + "Rebol/Core linux-x64 shared library" [ + name: %librebol3-core-linux-x64 + ;lflag: "-Wl,-install_name,'/usr/local/lib/librebol-core.3.so'" + :target-linux + :include-rebol-core + :make-x64-dll + ] + "Rebol/Core linux-x64 host application" [ + name: %host-core-linux-x64 + shared: %librebol3-core-linux-x64 + :target-linux + :include-rebol-core + :make-x64-host + ] ] @@ -1490,6 +1530,24 @@ eggs: [ :cross-linux-aarch64 :make-exe ] + ;@@ sudo apt-get install gcc-riscv64-linux-gnu + "Cross-compile Rebol/Base (riscv64)" [ + name: %rebol3-base-linux-riscv64 + :cross-linux-riscv64 + :make-exe + ] + "Cross-compile Rebol/Core (riscv64)" [ + name: %rebol3-core-linux-riscv64 + :include-rebol-core + :cross-linux-riscv64 + :make-exe + ] + "Cross-compile Rebol/Bulk (riscv64)" [ + name: %rebol3-bulk-linux-riscv64 + :include-rebol-bulk + :cross-linux-riscv64 + :make-exe + ] ] #if macOS? [ "Rebol/Base macos-x64" [ From e1247efa6567636c5b41a3f006a7882f4430dd25 Mon Sep 17 00:00:00 2001 From: Oldes Date: Tue, 30 Jan 2024 21:25:01 +0100 Subject: [PATCH 44/60] Build: make it possible to build 32bit Linux version on 64bit host --- make/rebol3.nest | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/make/rebol3.nest b/make/rebol3.nest index cce52dd52b..660c9c708a 100644 --- a/make/rebol3.nest +++ b/make/rebol3.nest @@ -1290,7 +1290,7 @@ eggs: [ ] ] #if Linux? [ - #if (system/build/arch = 'x86) [ + #if (find [x86 x64] system/build/arch) [ "Rebol/Base linux-x86" [ name: %rebol3-base-linux-x86 :target-linux @@ -1308,8 +1308,6 @@ eggs: [ :include-rebol-bulk :make-x86-exe ] - ] - #if (system/build/arch = 'x64) [ "Rebol/Base linux-x64" [ name: %rebol3-base-linux-x64 :target-linux From d4364df0e4f48944cb36beba1fdbc32d6d109e9f Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 1 Feb 2024 10:46:10 +0100 Subject: [PATCH 45/60] FIX: saving a file into a zip archive resolves: https://github.com/Oldes/Rebol-issues/issues/2588 --- src/mezz/codec-zip.reb | 2 +- src/tests/units/codecs-test.r3 | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/mezz/codec-zip.reb b/src/mezz/codec-zip.reb index e6926efa97..7cc8765f45 100644 --- a/src/mezz/codec-zip.reb +++ b/src/mezz/codec-zip.reb @@ -166,7 +166,7 @@ register-codec [ try/with [ spec: query/mode file [type: date:] either spec [ - file-name: find/tail file root + file-name: any [find/tail file root file] either spec/type = 'dir [ dir: file add-data file-name spec diff --git a/src/tests/units/codecs-test.r3 b/src/tests/units/codecs-test.r3 index e398c21e94..0f0257a395 100644 --- a/src/tests/units/codecs-test.r3 +++ b/src/tests/units/codecs-test.r3 @@ -308,6 +308,31 @@ if find codecs 'zip [ --assert block? select data %ico/icon_128.png delete %ico.zip + --test-- "Saving file to zip" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2588 + write %temp.txt "Ahoj!" + --assert all [ + not error? try [save %temp.zip %temp.txt] + block? data: load %temp.zip + data/1 = %temp.txt + data/2/2 = #{41686F6A21} + ] + delete %temp.zip + delete %temp.txt + + make-dir %temp/ + write %temp/temp.txt "Ahoj!" + --assert all [ + not error? try [save %temp.zip %temp/] + block? data: load %temp.zip + data/1 = %temp/ + none? data/2/2 + data/3 = %temp/temp.txt + data/4/2 = #{41686F6A21} + ] + delete-dir %temp/ + + --test-- "Encode ZIP using wildcard" --assert not error? try [save %temp.zip %units/files/issue-2186*.txt] data: load %temp.zip From dad1e5feb05474795358a29cb2e06a2053612191 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 1 Feb 2024 10:55:05 +0100 Subject: [PATCH 46/60] TEST: https://github.com/Oldes/Rebol-issues/issues/2588 --- src/tests/units/codecs-test.r3 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/units/codecs-test.r3 b/src/tests/units/codecs-test.r3 index 0f0257a395..1384959acb 100644 --- a/src/tests/units/codecs-test.r3 +++ b/src/tests/units/codecs-test.r3 @@ -330,6 +330,7 @@ if find codecs 'zip [ data/3 = %temp/temp.txt data/4/2 = #{41686F6A21} ] + delete %temp.zip delete-dir %temp/ From da4718b39c376b323799ecabe1491fae899ad036 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Mon, 5 Feb 2024 00:43:09 +0100 Subject: [PATCH 47/60] FEAT: not using hashing for small enough maps (reduces memory usage) related to: https://github.com/Oldes/Rebol3/commit/7091c94935297d63a4f670241cf62201d4addb76 --- src/core/n-sets.c | 7 +--- src/core/t-block.c | 49 +++++++++++++++++++++++++ src/core/t-map.c | 79 ++++++++++++++++++++++++++++++---------- src/include/reb-config.h | 1 + 4 files changed, 111 insertions(+), 25 deletions(-) diff --git a/src/core/n-sets.c b/src/core/n-sets.c index d62032e51d..82a4d8ed58 100644 --- a/src/core/n-sets.c +++ b/src/core/n-sets.c @@ -90,11 +90,8 @@ enum { if (GET_FLAG(flags, SOP_BOTH)) i += VAL_LEN(val2); retser = BUF_EMIT; // use preallocated shared block Resize_Series(retser, i); - hret = Make_Hash_Array(i); // allocated - - // Optimization note: !! - // This code could be optimized for small blocks by not hashing them - // and extending Find_Key to do a FIND on the value itself w/o the hash. + // don't hash small blocks... + hret = (i <= MIN_DICT) ? NULL : Make_Hash_Array(i); // allocated do { // Check what is in first series/map but not in second series/map: diff --git a/src/core/t-block.c b/src/core/t-block.c index 5e3397c4f9..66345b0613 100644 --- a/src/core/t-block.c +++ b/src/core/t-block.c @@ -198,6 +198,55 @@ static void No_Nones_Or_Logic(REBVAL *arg) { } } +/*********************************************************************** +** +*/ REBCNT Find_Block_Key(REBSER* series, REBVAL* key, REBCNT skip, REBOOL cased) +/* +** Try to find the key value in the block. +** +** RETURNS: the index to the KEY or NOT_FOUND if there is none. +** +***********************************************************************/ +{ + REBSER* hser = series->series; // can be null + REBCNT* hashes = NULL; + REBCNT hash; + REBCNT n; + REBVAL* val; + + val = BLK_HEAD(series); + if (ANY_WORD(key)) { + for (n = 0; n < series->tail; n += skip, val += skip) { + if ( + ANY_WORD(val) && ( + VAL_WORD_SYM(key) == VAL_BIND_SYM(val) || + (!cased && VAL_WORD_CANON(key) == VAL_BIND_CANON(val)) + ) + ) { + return n; + } + } + } + else if (ANY_BINSTR(key)) { + for (n = 0; n < series->tail; n += skip, val += skip) { + if ( + VAL_TYPE(val) == VAL_TYPE(key) + && 0 == Compare_String_Vals(key, val, (REBOOL)(!IS_BINARY(key) && !cased)) + ) { + return n; + } + } + } + else { + for (n = 0; n < series->tail; n += skip, val += skip) { + if (VAL_TYPE(val) == VAL_TYPE(key) && 0 == Cmp_Value(key, val, cased)) { + return n; + } + } + } + return NOT_FOUND; +} + /*********************************************************************** ** diff --git a/src/core/t-map.c b/src/core/t-map.c index ff89eb982a..e84a0c7b33 100644 --- a/src/core/t-map.c +++ b/src/core/t-map.c @@ -93,7 +93,8 @@ REBSER *blk = Make_Block(size*2); REBSER *ser = 0; - ser = Make_Hash_Array(size); + // Use hashing only when there is more then MIN_DICT keys. + if (size > MIN_DICT) ser = Make_Hash_Array(size); blk->series = ser; @@ -124,6 +125,19 @@ REBCNT n; REBVAL *val; + if (!hser) { + // If there are no hashes for the keys, use plain linear search... + hash = Find_Block_Key(series, key, wide, cased); + if (hash == NOT_FOUND) { + if (mode > 1) { + // Append new value the target series: + Append_Series(series, (REBYTE*)key, wide); + } + return -1; + } + return hash; + } + // Compute hash for value: len = hser->tail; hash = Hash_Value(key, len); @@ -214,18 +228,43 @@ ** and val is SET, create the entry and store the key and ** val. ** -** RETURNS: the index to the VALUE or zero if there is none. +** RETURNS: the index to the VALUE or NOT_FOUND if there is none. ** ***********************************************************************/ { REBSER *hser = series->series; // can be null - REBCNT *hashes; + REBCNT *hashes = NULL; REBCNT hash; REBCNT n; REBVAL *set; - if (IS_NONE(key) || hser == NULL) return 0; + if (IS_NONE(key)) return NOT_FOUND; + + // We may not be large enough yet for the hash table to + // be worthwhile, so just do a linear search: + if (!hser) { + if (series->tail <= MIN_DICT * 2) { + hash = Find_Block_Key(series, key, 2, cased); + if (hash != NOT_FOUND) { + hash++; // position of the value + // Key already exists so update the value, if needed... + if (val) { + set = BLK_SKIP(series, hash); + *set = *val; + } + // Return + return hash; + } + if (!val) return NOT_FOUND; + hash /= 2; + goto new_entry; + } + // Add hash table: + //Print("hash added %d", series->tail); + series->series = hser = Make_Hash_Array(series->tail); + Rehash_Hash(series); + } // Get hash table, expand it if needed: if (series->tail > hser->tail/2) { Expand_Hash(hser); // modifies size value @@ -237,16 +276,17 @@ n = hashes[hash]; // Just a GET of value: - if (!val) return n; + if (!val) return ((n-1)*2)+1; // Must set the value: if (n) { // re-set it: - set = BLK_SKIP(series, ((n-1)*2)); // find the key - VAL_CLR_OPT(set++, OPTS_HIDE); // clear HIDE flag in case it was removed key; change to value position - *set = *val; // set the value - return n; + n = (n-1)*2; // index of the key + set = BLK_SKIP(series, n); // find the key + VAL_CLR_OPT(set++, OPTS_HIDE); // clear HIDE flag in case it was removed key; change to value position + *set = *val; // set the value + return n+1; // index of the value } - +new_entry: // Create new entry: #ifndef DO_NOT_NORMALIZE_MAP_KEYS // append key @@ -275,8 +315,8 @@ #endif // append value Append_Val(series, val); // no Copy_Series_Value(val) on strings - - return (hashes[hash] = series->tail/2); + if (hashes) hashes[hash] = series->tail / 2; // Hash index is not a real index position of the value! + return series->tail; // Index of the new value. } @@ -320,9 +360,9 @@ n = Find_Entry(VAL_SERIES(data), pvs->select, val, FALSE); - if (!n) return PE_NONE; + if (n == NOT_FOUND) return PE_NONE; - pvs->value = VAL_BLK_SKIP(data, ((n-1)*2)+1); + pvs->value = VAL_BLK_SKIP(data, n); return PE_OK; } @@ -507,8 +547,8 @@ case A_SELECT: case A_FIND: n = Find_Entry(series, arg, 0, Find_Refines(ds, AM_SELECT_CASE) ? AM_FIND_CASE : 0); - if (!n) return R_NONE; - *D_RET = *VAL_BLK_SKIP(val, ((n-1)*2)+((action == A_FIND)?0:1)); + if (n == NOT_FOUND) return R_NONE; + *D_RET = *VAL_BLK_SKIP(val, n - ((action == A_FIND)?1:0)); // `find` returns the key break; case A_INSERT: @@ -534,10 +574,9 @@ case A_REMOVE: //O: throw an error if /part is used? n = Find_Entry(series, D_ARG(ARG_REMOVE_KEY_ARG), 0, TRUE); - if (n) { - n = (n-1)*2; - VAL_SET_OPT(VAL_BLK_SKIP(val, n), OPTS_HIDE); - VAL_SET(VAL_BLK_SKIP(val, n+1), REB_NONE); // set value to none (so the old one may be GCed) + if (n != NOT_FOUND) { + VAL_SET_OPT(VAL_BLK_SKIP(val, n-1), OPTS_HIDE); // hide the key + VAL_SET(VAL_BLK_SKIP(val, n), REB_NONE); // set value to none (so the old one may be GCed) } return R_ARG1; diff --git a/src/include/reb-config.h b/src/include/reb-config.h index eb78560641..1507849ff5 100644 --- a/src/include/reb-config.h +++ b/src/include/reb-config.h @@ -77,6 +77,7 @@ These are now obsolete (as of A107) and should be removed: #include REBOL_OPTIONS_FILE #endif +#define MIN_DICT 16 // Maximum number of keys in a map withouth hashing //* Common ************************************************************* From ab42ca5231abdbc73f11ece0bc8b0dd6953f553b Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Mon, 5 Feb 2024 01:20:59 +0100 Subject: [PATCH 48/60] FEAT: tiny optimization --- src/core/t-block.c | 4 ++-- src/core/t-map.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/t-block.c b/src/core/t-block.c index 66345b0613..608eefc338 100644 --- a/src/core/t-block.c +++ b/src/core/t-block.c @@ -210,7 +210,6 @@ static void No_Nones_Or_Logic(REBVAL *arg) { { REBSER* hser = series->series; // can be null REBCNT* hashes = NULL; - REBCNT hash; REBCNT n; REBVAL* val; @@ -228,10 +227,11 @@ static void No_Nones_Or_Logic(REBVAL *arg) { } } else if (ANY_BINSTR(key)) { + cased = !(IS_BINARY(key) || cased); for (n = 0; n < series->tail; n += skip, val += skip) { if ( VAL_TYPE(val) == VAL_TYPE(key) - && 0 == Compare_String_Vals(key, val, (REBOOL)(!IS_BINARY(key) && !cased)) + && 0 == Compare_String_Vals(key, val, cased) ) { return n; } diff --git a/src/core/t-map.c b/src/core/t-map.c index e84a0c7b33..20594bfd26 100644 --- a/src/core/t-map.c +++ b/src/core/t-map.c @@ -165,11 +165,12 @@ } } else if (ANY_BINSTR(key)) { + cased = !(IS_BINARY(key) || cased); while (NZ(n = hashes[hash])) { val = BLK_SKIP(series, (n-1) * wide); if ( VAL_TYPE(val) == VAL_TYPE(key) - && 0 == Compare_String_Vals(key, val, (REBOOL)(!IS_BINARY(key) && !cased)) + && 0 == Compare_String_Vals(key, val, cased) ) return hash; hash += skip; if (hash >= len) hash -= len; From a674fa6ac9fd9472896861ccc48ddc201617e771 Mon Sep 17 00:00:00 2001 From: Oldes Date: Mon, 5 Feb 2024 12:27:13 +0100 Subject: [PATCH 49/60] TEST: https://github.com/Oldes/Rebol-issues/issues/1075 --- src/tests/units/series-test.r3 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tests/units/series-test.r3 b/src/tests/units/series-test.r3 index e838d8ce36..45ddaa0f44 100644 --- a/src/tests/units/series-test.r3 +++ b/src/tests/units/series-test.r3 @@ -2524,6 +2524,11 @@ Rebol [ --assert [1 2 3 4] = deduplicate/skip b: [1 2 1 2 3 4] 2 --assert [1 2 3 4] = b +--test-- "unique on block of blocks" + ;@@ https://github.com/Oldes/Rebol-issues/issues/1075 + --assert [[ ]] = unique [[] []] + --assert [[1]] = unique [[1] [1]] + --test-- "unique with unset and none" ;@@ https://github.com/Oldes/Rebol-issues/issues/1124 ;@@ https://github.com/Oldes/Rebol-issues/issues/1592 From f25ddfa9239befaab611b209d5b64146b61b75a1 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Tue, 6 Feb 2024 00:36:20 +0100 Subject: [PATCH 50/60] FEAT: implemented optional `XXH3`, `XXH32`, `XXH64` and `XXH128` checksums --- NOTICE | 3 + make/rebol3.nest | 6 + src/boot/words.reb | 4 + src/core/n-crypt.c | 6 + src/core/n-strings.c | 24 + src/core/p-checksum.c | 62 +- src/core/u-xxhash.c | 165 + src/include/sys-checksum.h | 35 + src/include/sys-xxhash.h | 7048 ++++++++++++++++++++++++++++++ src/tests/units/checksum-test.r3 | 87 + 10 files changed, 7439 insertions(+), 1 deletion(-) create mode 100644 src/core/u-xxhash.c create mode 100644 src/include/sys-xxhash.h diff --git a/NOTICE b/NOTICE index 7d67d2d441..75ffa1198d 100644 --- a/NOTICE +++ b/NOTICE @@ -58,6 +58,9 @@ Credits for Non-REBOL orginated C files and modules Copyright (c) 2021, Dominic Szablewski https://phoboslab.org The MIT License(MIT) - https://github.com/phoboslab/qoi +* xxHash (optional): + Copyright (C) 2012-2023 Yann Collet - https://github.com/Cyan4973/xxHash + BSD 2-Clause License Credits for currently deprecated and or unused code --------------------------------------------------- diff --git a/make/rebol3.nest b/make/rebol3.nest index 660c9c708a..a06c608bb3 100644 --- a/make/rebol3.nest +++ b/make/rebol3.nest @@ -766,6 +766,11 @@ include-base36-encoding: [ config: INCLUDE_BASE36 ] +include-xxhash: [ + config: INCLUDE_XXHASH + file: %core/u-xxhash.c +] + ;- native additional compressions: include-lzma-compression: [ config: INCLUDE_LZMA @@ -930,6 +935,7 @@ include-rebol-core: [ :include-cryptography :include-bincode :include-iconv + :include-xxhash :include-mail :include-prot-https diff --git a/src/boot/words.reb b/src/boot/words.reb index 3b41745218..40e71a32db 100644 --- a/src/boot/words.reb +++ b/src/boot/words.reb @@ -212,6 +212,10 @@ sha256 sha384 sha512 ripemd160 +xxh3 +xxh32 +xxh64 +xxh128 sha3-224 sha3-256 sha3-384 diff --git a/src/core/n-crypt.c b/src/core/n-crypt.c index 8dd1eaaecb..6bb3e23e70 100644 --- a/src/core/n-crypt.c +++ b/src/core/n-crypt.c @@ -220,6 +220,12 @@ static mbedtls_ctr_drbg_context ctr_drbg; add_ec_word(SYM_SHA3_256) add_ec_word(SYM_SHA3_384) add_ec_word(SYM_SHA3_512) +#endif +#ifdef INCLUDE_XXHASH + add_ec_word(SYM_XXH3) + add_ec_word(SYM_XXH32) + add_ec_word(SYM_XXH64) + add_ec_word(SYM_XXH128) #endif add_ec_word(SYM_TCP) } diff --git a/src/core/n-strings.c b/src/core/n-strings.c index 344b84b385..6c5faa4979 100644 --- a/src/core/n-strings.c +++ b/src/core/n-strings.c @@ -70,6 +70,12 @@ static struct digest { {SHA3_256, SHA3_256_Starts, SHA3_Update, SHA3_256_Finish, SHA3_CtxSize, SYM_SHA3_256, 32, 64}, {SHA3_384, SHA3_384_Starts, SHA3_Update, SHA3_384_Finish, SHA3_CtxSize, SYM_SHA3_384, 48, 128}, {SHA3_512, SHA3_512_Starts, SHA3_Update, SHA3_512_Finish, SHA3_CtxSize, SYM_SHA3_512, 64, 128}, +#endif +#ifdef INCLUDE_MD4 + {HashXXH3, XXH3_Starts, XXH3_Update, XXH3_Finish, XXH3_CtxSize, SYM_XXH3, 8, 64}, + {HashXXH32, XXH32_Starts, XXH32_Update, XXH32_Finish, XXH32_CtxSize, SYM_XXH32, 4, 64}, + {HashXXH64, XXH64_Starts, XXH64_Update, XXH64_Finish, XXH64_CtxSize, SYM_XXH64, 8, 64}, + {HashXXH128, XXH128_Starts, XXH128_Update, XXH128_Finish, XXH128_CtxSize, SYM_XXH128, 16, 64}, #endif {0} @@ -138,6 +144,24 @@ static struct digest { MD4(input, length, output); *olen = 16; break; +#endif +#ifdef INCLUDE_XXHASH + case SYM_XXH3: + HashXXH3(input, length, output); + *olen = 8; + break; + case SYM_XXH32: + HashXXH32(input, length, output); + *olen = 4; + break; + case SYM_XXH64: + HashXXH64(input, length, output); + *olen = 8; + break; + case SYM_XXH128: + HashXXH128(input, length, output); + *olen = 16; + break; #endif default: return FALSE; diff --git a/src/core/p-checksum.c b/src/core/p-checksum.c index fee443c6f7..603b435978 100644 --- a/src/core/p-checksum.c +++ b/src/core/p-checksum.c @@ -34,9 +34,9 @@ #include REBOL_OPTIONS_FILE #endif -#ifdef INCLUDE_MBEDTLS #include "sys-core.h" #include "sys-checksum.h" +#ifdef INCLUDE_MBEDTLS #include "reb-net.h" #include "mbedtls/md4.h" #include "mbedtls/md5.h" @@ -140,6 +140,24 @@ *ctx = sizeof(SHA512_CTX); *blk = SHA512_DIGEST_LENGTH; return; +#endif +#ifdef INCLUDE_XXHASH + case SYM_XXH3: + *ctx = sizeof(XXH3_CTX); + *blk = 8; + break; + case SYM_XXH32: + *ctx = sizeof(XXH32_CTX); + *blk = 4; + break; + case SYM_XXH64: + *ctx = sizeof(XXH64_CTX); + *blk = 8; + break; + case SYM_XXH128: + *ctx = sizeof(XXH128_CTX); + *blk = 16; + break; #endif default: *ctx = *blk = 0; @@ -225,6 +243,20 @@ case SYM_SHA512: SHA512_Starts((SHA512_CTX*)VAL_BIN(ctx)); return TRUE; +#endif +#ifdef INCLUDE_XXHASH + case SYM_XXH3: + XXH3_Starts((XXH3_CTX*)VAL_BIN(ctx)); + return TRUE; + case SYM_XXH32: + XXH32_Starts((XXH32_CTX*)VAL_BIN(ctx)); + return TRUE; + case SYM_XXH64: + XXH64_Starts((XXH64_CTX*)VAL_BIN(ctx)); + return TRUE; + case SYM_XXH128: + XXH128_Starts((XXH128_CTX*)VAL_BIN(ctx)); + return TRUE; #endif } return FALSE; @@ -348,6 +380,20 @@ case SYM_SHA512: SHA512_Update((SHA512_CTX*)VAL_BIN(ctx), VAL_BIN_SKIP(arg, pos), part); break; +#endif +#ifdef INCLUDE_XXHASH + case SYM_XXH3: + XXH3_Update((XXH3_CTX*)VAL_BIN(ctx), VAL_BIN_SKIP(arg, pos), part); + break; + case SYM_XXH32: + XXH32_Update((XXH32_CTX*)VAL_BIN(ctx), VAL_BIN_SKIP(arg, pos), part); + break; + case SYM_XXH64: + XXH64_Update((XXH64_CTX*)VAL_BIN(ctx), VAL_BIN_SKIP(arg, pos), part); + break; + case SYM_XXH128: + XXH128_Update((XXH128_CTX*)VAL_BIN(ctx), VAL_BIN_SKIP(arg, pos), part); + break; #endif } break; @@ -430,6 +476,20 @@ case SYM_SHA512: SHA512_Finish((SHA512_CTX*)DS_TOP, VAL_BIN_DATA(data)); break; +#endif +#ifdef INCLUDE_XXHASH + case SYM_XXH3: + XXH3_Finish((XXH3_CTX*)DS_TOP, VAL_BIN_DATA(data)); + break; + case SYM_XXH32: + XXH32_Finish((XXH32_CTX*)DS_TOP, VAL_BIN_DATA(data)); + break; + case SYM_XXH64: + XXH64_Finish((XXH64_CTX*)DS_TOP, VAL_BIN_DATA(data)); + break; + case SYM_XXH128: + XXH128_Finish((XXH128_CTX*)DS_TOP, VAL_BIN_DATA(data)); + break; #endif } if(action == A_READ) *D_RET = *data; diff --git a/src/core/u-xxhash.c b/src/core/u-xxhash.c new file mode 100644 index 0000000000..01097e445a --- /dev/null +++ b/src/core/u-xxhash.c @@ -0,0 +1,165 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2012-2023 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * xxhash.c instantiates functions defined in xxhash.h + */ + +#include "sys-core.h" + +#ifdef INCLUDE_XXHASH +#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ +#define XXH_IMPLEMENTATION /* access definitions */ + +#include "sys-xxhash.h" + +/*********************************************************************** +** +*/ REBYTE *HashXXH3(REBYTE *d, REBCNT n, REBYTE *md) +/* +***********************************************************************/ +{ + // d is data, n is length + XXH64_hash_t const hash = XXH3_64bits(d, n); + XXH64_canonicalFromHash(md, hash); + return md; +} +/*********************************************************************** +** +*/ REBYTE *HashXXH32(REBYTE *d, REBCNT n, REBYTE *md) +/* +***********************************************************************/ +{ + XXH32_hash_t const hash = XXH32(d, n, 0); + XXH32_canonicalFromHash(md, hash); + return md; +} +/*********************************************************************** +** +*/ REBYTE *HashXXH64(REBYTE *d, REBCNT n, REBYTE *md) +/* +***********************************************************************/ +{ + // d is data, n is length + XXH64_hash_t const hash = XXH64(d, n, 0); + XXH64_canonicalFromHash(md, hash); + return md; +} +/*********************************************************************** +** +*/ REBYTE* HashXXH128(REBYTE* d, REBCNT n, REBYTE* md) +/* +***********************************************************************/ +{ + // d is data, n is length + XXH128_hash_t const hash = XXH128(d, n, 0); + XXH128_canonicalFromHash(md, hash); + return md; +} +int XXH3_CtxSize(void) { return sizeof(XXH3_state_t); } +int XXH32_CtxSize(void) { return sizeof(XXH32_state_t); } +int XXH64_CtxSize(void) { return sizeof(XXH64_state_t); } +int XXH128_CtxSize(void) { return sizeof(XXH3_state_t); } + +void XXH3_Starts( XXH3_state_t *ctx ) +{ + XXH3_64bits_reset(ctx); +} +void XXH3_Update( XXH3_state_t *ctx, + const unsigned char *input, + size_t ilen ) +{ + XXH3_64bits_update( ctx, input, ilen ); +} +void XXH3_Finish(XXH3_state_t*ctx, + unsigned char output[64] ) +{ + XXH64_hash_t const hash = XXH3_64bits_digest(ctx); + XXH64_canonicalFromHash(output, hash); +} + +void XXH32_Starts( XXH32_state_t *ctx ) +{ + ctx = XXH32_createState(); + XXH32_reset(ctx, 0); +} +void XXH32_Update( XXH32_state_t *ctx, + const unsigned char *input, + size_t ilen ) +{ + XXH32_update( ctx, input, ilen ); +} +void XXH32_Finish(XXH32_state_t*ctx, + unsigned char output[64] ) +{ + XXH32_hash_t const hash = XXH32_digest(ctx); + XXH32_canonicalFromHash(output, hash); +} + +void XXH64_Starts( XXH64_state_t *ctx ) +{ + ctx = XXH64_createState(); + XXH64_reset(ctx, 0); +} +void XXH64_Update( XXH64_state_t *ctx, + const unsigned char *input, + size_t ilen ) +{ + XXH64_update( ctx, input, ilen ); +} +void XXH64_Finish(XXH64_state_t*ctx, + unsigned char output[64] ) +{ + XXH64_hash_t const hash = XXH64_digest(ctx); + XXH64_canonicalFromHash(output, hash); +} + +void XXH128_Starts( XXH3_state_t *ctx ) +{ + XXH3_128bits_reset(ctx); +} +void XXH128_Update( XXH3_state_t *ctx, + const unsigned char *input, + size_t ilen ) +{ + XXH3_128bits_update( ctx, input, ilen ); +} +void XXH128_Finish(XXH3_state_t*ctx, + unsigned char output[16] ) +{ + XXH128_hash_t const hash = XXH3_128bits_digest(ctx); + XXH128_canonicalFromHash((XXH128_canonical_t*)output, hash); +} + +#endif diff --git a/src/include/sys-checksum.h b/src/include/sys-checksum.h index b61dfcd57b..a160e1b510 100644 --- a/src/include/sys-checksum.h +++ b/src/include/sys-checksum.h @@ -97,4 +97,39 @@ void SHA3_224_Finish(void* c, REBYTE* md); void SHA3_256_Finish(void* c, REBYTE* md); void SHA3_384_Finish(void* c, REBYTE* md); void SHA3_512_Finish(void* c, REBYTE* md); +#endif + +#ifdef INCLUDE_XXHASH +#define XXH_STATIC_LINKING_ONLY +#include "sys-xxhash.h" + +#define XXH3_CTX XXH3_state_t +#define XXH32_CTX XXH32_state_t +#define XXH64_CTX XXH64_state_t +#define XXH128_CTX XXH3_state_t +REBYTE* HashXXH3(REBYTE*, REBCNT, REBYTE*); +REBYTE* HashXXH32(REBYTE*, REBCNT, REBYTE*); +REBYTE* HashXXH64(REBYTE*, REBCNT, REBYTE*); +REBYTE* HashXXH128(REBYTE*, REBCNT, REBYTE*); + +void XXH3_Starts(void* c); +void XXH3_Update(void* c, REBYTE* data, REBCNT len); +void XXH3_Finish(void* c, REBYTE* md); +int XXH3_CtxSize(void); + +void XXH32_Starts(void* c); +void XXH32_Update(void* c, REBYTE* data, REBCNT len); +void XXH32_Finish(void* c, REBYTE* md); +int XXH32_CtxSize(void); + +void XXH64_Starts(void* c); +void XXH64_Update(void* c, REBYTE* data, REBCNT len); +void XXH64_Finish(void* c, REBYTE* md); +int XXH64_CtxSize(void); + +void XXH128_Starts(void* c); +void XXH128_Update(void* c, REBYTE* data, REBCNT len); +void XXH128_Finish(void* c, REBYTE* md); +int XXH128_CtxSize(void); + #endif \ No newline at end of file diff --git a/src/include/sys-xxhash.h b/src/include/sys-xxhash.h new file mode 100644 index 0000000000..d11f0f6333 --- /dev/null +++ b/src/include/sys-xxhash.h @@ -0,0 +1,7048 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Header File + * Copyright (C) 2012-2023 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/*! + * @mainpage xxHash + * + * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed + * limits. + * + * It is proposed in four flavors, in three families: + * 1. @ref XXH32_family + * - Classic 32-bit hash function. Simple, compact, and runs on almost all + * 32-bit and 64-bit systems. + * 2. @ref XXH64_family + * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most + * 64-bit systems (but _not_ 32-bit systems). + * 3. @ref XXH3_family + * - Modern 64-bit and 128-bit hash function family which features improved + * strength and performance across the board, especially on smaller data. + * It benefits greatly from SIMD and 64-bit without requiring it. + * + * Benchmarks + * --- + * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. + * The open source benchmark program is compiled with clang v10.0 using -O3 flag. + * + * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | + * | -------------------- | ------- | ----: | ---------------: | ------------------: | + * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | + * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | + * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | + * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | + * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | + * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | + * | RAM sequential read | | N/A | 28.0 GB/s | N/A | + * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | + * | City64 | | 64 | 22.0 GB/s | 76.6 | + * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | + * | City128 | | 128 | 21.7 GB/s | 57.7 | + * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | + * | XXH64() | | 64 | 19.4 GB/s | 71.0 | + * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | + * | Mum | | 64 | 18.0 GB/s | 67.0 | + * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | + * | XXH32() | | 32 | 9.7 GB/s | 71.9 | + * | City32 | | 32 | 9.1 GB/s | 66.0 | + * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | + * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | + * | SipHash* | | 64 | 3.0 GB/s | 43.2 | + * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | + * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | + * | FNV64 | | 64 | 1.2 GB/s | 62.7 | + * | Blake2* | | 256 | 1.1 GB/s | 5.1 | + * | SHA1* | | 160 | 0.8 GB/s | 5.6 | + * | MD5* | | 128 | 0.6 GB/s | 7.8 | + * @note + * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, + * even though it is mandatory on x64. + * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic + * by modern standards. + * - Small data velocity is a rough average of algorithm's efficiency for small + * data. For more accurate information, see the wiki. + * - More benchmarks and strength tests are found on the wiki: + * https://github.com/Cyan4973/xxHash/wiki + * + * Usage + * ------ + * All xxHash variants use a similar API. Changing the algorithm is a trivial + * substitution. + * + * @pre + * For functions which take an input and length parameter, the following + * requirements are assumed: + * - The range from [`input`, `input + length`) is valid, readable memory. + * - The only exception is if the `length` is `0`, `input` may be `NULL`. + * - For C++, the objects must have the *TriviallyCopyable* property, as the + * functions access bytes directly as if it was an array of `unsigned char`. + * + * @anchor single_shot_example + * **Single Shot** + * + * These functions are stateless functions which hash a contiguous block of memory, + * immediately returning the result. They are the easiest and usually the fastest + * option. + * + * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which hashes a null terminated string with XXH32(). + * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) + * { + * // NULL pointers are only valid if the length is zero + * size_t length = (string == NULL) ? 0 : strlen(string); + * return XXH32(string, length, seed); + * } + * @endcode + * + * + * @anchor streaming_example + * **Streaming** + * + * These groups of functions allow incremental hashing of unknown size, even + * more than what would fit in a size_t. + * + * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() + * + * @code{.c} + * #include + * #include + * #include "xxhash.h" + * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). + * XXH64_hash_t hashFile(FILE* f) + * { + * // Allocate a state struct. Do not just use malloc() or new. + * XXH3_state_t* state = XXH3_createState(); + * assert(state != NULL && "Out of memory!"); + * // Reset the state to start a new hashing session. + * XXH3_64bits_reset(state); + * char buffer[4096]; + * size_t count; + * // Read the file in chunks + * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { + * // Run update() as many times as necessary to process the data + * XXH3_64bits_update(state, buffer, count); + * } + * // Retrieve the finalized hash. This will not change the state. + * XXH64_hash_t result = XXH3_64bits_digest(state); + * // Free the state. Do not use free(). + * XXH3_freeState(state); + * return result; + * } + * @endcode + * + * Streaming functions generate the xxHash value from an incremental input. + * This method is slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * An XXH state must first be allocated using `XXH*_createState()`. + * + * Start a new hash by initializing the state with a seed using `XXH*_reset()`. + * + * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. + * + * The function returns an error code, with 0 meaning OK, and any other value + * meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a + * digest, and generate new hash values later on by invoking `XXH*_digest()`. + * + * When done, release the state using `XXH*_freeState()`. + * + * + * @anchor canonical_representation_example + * **Canonical Representation** + * + * The default return values from XXH functions are unsigned 32, 64 and 128 bit + * integers. + * This the simplest and fastest format for further post-processing. + * + * However, this leaves open the question of what is the order on the byte level, + * since little and big endian conventions will store the same number differently. + * + * The canonical representation settles this issue by mandating big-endian + * convention, the same convention as human-readable numbers (large digits first). + * + * When writing hash values to storage, sending them over a network, or printing + * them, it's highly recommended to use the canonical representation to ensure + * portability across a wider range of systems, present and future. + * + * The following functions allow transformation of hash values to and from + * canonical format. + * + * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(), + * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(), + * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(), + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which prints XXH32_hash_t in human readable format + * void printXxh32(XXH32_hash_t hash) + * { + * XXH32_canonical_t cano; + * XXH32_canonicalFromHash(&cano, hash); + * size_t i; + * for(i = 0; i < sizeof(cano.digest); ++i) { + * printf("%02x", cano.digest[i]); + * } + * printf("\n"); + * } + * + * // Example for a function which converts XXH32_canonical_t to XXH32_hash_t + * XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano) + * { + * XXH32_hash_t hash = XXH32_hashFromCanonical(&cano); + * return hash; + * } + * @endcode + * + * + * @file xxhash.h + * xxHash prototypes and implementation + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/* **************************** + * INLINE mode + ******************************/ +/*! + * @defgroup public Public API + * Contains details on the public xxHash functions. + * @{ + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Gives access to internal state declaration, required for static allocation. + * + * Incompatible with dynamic linking, due to risks of ABI changes. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #include "xxhash.h" + * @endcode + */ +# define XXH_STATIC_LINKING_ONLY +/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ + +/*! + * @brief Gives access to internal definitions. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #define XXH_IMPLEMENTATION + * #include "xxhash.h" + * @endcode + */ +# define XXH_IMPLEMENTATION +/* Do not undef XXH_IMPLEMENTATION for Doxygen */ + +/*! + * @brief Exposes the implementation and marks all functions as `inline`. + * + * Use these build macros to inline xxhash into the target unit. + * Inlining improves performance on small inputs, especially when the length is + * expressed as a compile-time constant: + * + * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html + * + * It also keeps xxHash symbols private to the unit, so they are not exported. + * + * Usage: + * @code{.c} + * #define XXH_INLINE_ALL + * #include "xxhash.h" + * @endcode + * Do not compile and link xxhash.o as a separate object, as it is not useful. + */ +# define XXH_INLINE_ALL +# undef XXH_INLINE_ALL +/*! + * @brief Exposes the implementation without marking functions as inline. + */ +# define XXH_PRIVATE_API +# undef XXH_PRIVATE_API +/*! + * @brief Emulate a namespace by transparently prefixing all symbols. + * + * If you want to include _and expose_ xxHash functions from within your own + * library, but also want to avoid symbol collisions with other libraries which + * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix + * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE + * (therefore, avoid empty or numeric values). + * + * Note that no change is required within the calling program as long as it + * includes `xxhash.h`: Regular symbol names will be automatically translated + * by this header. + */ +# define XXH_NAMESPACE /* YOUR NAME HERE */ +# undef XXH_NAMESPACE +#endif + +#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ + && !defined(XXH_INLINE_ALL_31684351384) + /* this section should be traversed only once */ +# define XXH_INLINE_ALL_31684351384 + /* give access to the advanced API, required to compile implementations */ +# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ +# define XXH_STATIC_LINKING_ONLY + /* make all functions private */ +# undef XXH_PUBLIC_API +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* note: this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif + + /* + * This part deals with the special case where a unit wants to inline xxHash, + * but "xxhash.h" has previously been included without XXH_INLINE_ALL, + * such as part of some previously included *.h header file. + * Without further action, the new include would just be ignored, + * and functions would effectively _not_ be inlined (silent failure). + * The following macros solve this situation by prefixing all inlined names, + * avoiding naming collision with previous inclusions. + */ + /* Before that, we unconditionally #undef all symbols, + * in case they were already defined with XXH_NAMESPACE. + * They will then be redefined for XXH_INLINE_ALL + */ +# undef XXH_versionNumber + /* XXH32 */ +# undef XXH32 +# undef XXH32_createState +# undef XXH32_freeState +# undef XXH32_reset +# undef XXH32_update +# undef XXH32_digest +# undef XXH32_copyState +# undef XXH32_canonicalFromHash +# undef XXH32_hashFromCanonical + /* XXH64 */ +# undef XXH64 +# undef XXH64_createState +# undef XXH64_freeState +# undef XXH64_reset +# undef XXH64_update +# undef XXH64_digest +# undef XXH64_copyState +# undef XXH64_canonicalFromHash +# undef XXH64_hashFromCanonical + /* XXH3_64bits */ +# undef XXH3_64bits +# undef XXH3_64bits_withSecret +# undef XXH3_64bits_withSeed +# undef XXH3_64bits_withSecretandSeed +# undef XXH3_createState +# undef XXH3_freeState +# undef XXH3_copyState +# undef XXH3_64bits_reset +# undef XXH3_64bits_reset_withSeed +# undef XXH3_64bits_reset_withSecret +# undef XXH3_64bits_update +# undef XXH3_64bits_digest +# undef XXH3_generateSecret + /* XXH3_128bits */ +# undef XXH128 +# undef XXH3_128bits +# undef XXH3_128bits_withSeed +# undef XXH3_128bits_withSecret +# undef XXH3_128bits_reset +# undef XXH3_128bits_reset_withSeed +# undef XXH3_128bits_reset_withSecret +# undef XXH3_128bits_reset_withSecretandSeed +# undef XXH3_128bits_update +# undef XXH3_128bits_digest +# undef XXH128_isEqual +# undef XXH128_cmp +# undef XXH128_canonicalFromHash +# undef XXH128_hashFromCanonical + /* Finally, free the namespace itself */ +# undef XXH_NAMESPACE + + /* employ the namespace for XXH_INLINE_ALL */ +# define XXH_NAMESPACE XXH_INLINE_ + /* + * Some identifiers (enums, type names) are not symbols, + * but they must nonetheless be renamed to avoid redeclaration. + * Alternative solution: do not redeclare them. + * However, this requires some #ifdefs, and has a more dispersed impact. + * Meanwhile, renaming can be achieved in a single place. + */ +# define XXH_IPREF(Id) XXH_NAMESPACE ## Id +# define XXH_OK XXH_IPREF(XXH_OK) +# define XXH_ERROR XXH_IPREF(XXH_ERROR) +# define XXH_errorcode XXH_IPREF(XXH_errorcode) +# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) +# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) +# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) +# define XXH32_state_s XXH_IPREF(XXH32_state_s) +# define XXH32_state_t XXH_IPREF(XXH32_state_t) +# define XXH64_state_s XXH_IPREF(XXH64_state_s) +# define XXH64_state_t XXH_IPREF(XXH64_state_t) +# define XXH3_state_s XXH_IPREF(XXH3_state_s) +# define XXH3_state_t XXH_IPREF(XXH3_state_t) +# define XXH128_hash_t XXH_IPREF(XXH128_hash_t) + /* Ensure the header is parsed again, even if it was previously included */ +# undef XXHASH_H_5627135585666179 +# undef XXHASH_H_STATIC_13879238742 +#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ + +/* **************************************************************** + * Stable API + *****************************************************************/ +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + +/*! @brief Marks a global symbol. */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +/* XXH32 */ +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +/* XXH64 */ +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +/* XXH3_64bits */ +# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) +# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) +# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) +# define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) +# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) +# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) +# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) +# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) +# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) +# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) +# define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) +# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) +# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) +# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) +# define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) +/* XXH3_128bits */ +# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) +# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) +# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) +# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) +# define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) +# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) +# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) +# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) +# define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) +# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) +# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) +# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) +# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) +# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) +# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) +#endif + + +/* ************************************* +* Compiler specifics +***************************************/ + +/* specific declaration modes for Windows */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#if defined (__GNUC__) +# define XXH_CONSTF __attribute__((const)) +# define XXH_PUREF __attribute__((pure)) +# define XXH_MALLOCF __attribute__((malloc)) +#else +# define XXH_CONSTF /* disable */ +# define XXH_PUREF +# define XXH_MALLOCF +#endif + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 8 +#define XXH_VERSION_RELEASE 2 +/*! @brief Version number, encoded as two digits each */ +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) + +/*! + * @brief Obtains the xxHash version. + * + * This is mostly useful when xxHash is compiled as a shared library, + * since the returned value comes from the library, as opposed to header file. + * + * @return @ref XXH_VERSION_NUMBER of the invoked library. + */ +XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); + + +/* **************************** +* Common basic types +******************************/ +#include /* size_t */ +/*! + * @brief Exit code for the streaming API. + */ +typedef enum { + XXH_OK = 0, /*!< OK */ + XXH_ERROR /*!< Error */ +} XXH_errorcode; + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* Don't show include */ +/*! + * @brief An unsigned 32-bit integer. + * + * Not necessarily defined to `uint32_t` but functionally equivalent. + */ +typedef uint32_t XXH32_hash_t; + +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint32_t XXH32_hash_t; + +#else +# include +# if UINT_MAX == 0xFFFFFFFFUL + typedef unsigned int XXH32_hash_t; +# elif ULONG_MAX == 0xFFFFFFFFUL + typedef unsigned long XXH32_hash_t; +# else +# error "unsupported platform: need a 32-bit type" +# endif +#endif + +/*! + * @} + * + * @defgroup XXH32_family XXH32 family + * @ingroup public + * Contains functions used in the classic 32-bit xxHash algorithm. + * + * @note + * XXH32 is useful for older platforms, with no or poor 64-bit performance. + * Note that the @ref XXH3_family provides competitive speed for both 32-bit + * and 64-bit systems, and offers true 64/128 bit hash results. + * + * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families + * @see @ref XXH32_impl for implementation details + * @{ + */ + +/*! + * @brief Calculates the 32-bit hash of @p input using xxHash32. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 32-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 32-bit xxHash32 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); + +#ifndef XXH_NO_STREAM +/*! + * @typedef struct XXH32_state_s XXH32_state_t + * @brief The opaque state struct for the XXH32 streaming API. + * + * @see XXH32_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH32_state_s XXH32_state_t; + +/*! + * @brief Allocates an @ref XXH32_state_t. + * + * @return An allocated pointer of @ref XXH32_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH32_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); +/*! + * @brief Frees an @ref XXH32_state_t. + * + * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH32_createState(). + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +/*! + * @brief Copies one @ref XXH32_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +/*! + * @brief Resets an @ref XXH32_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 32-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH32_update(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH32_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH32_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 32-bit xxHash32 value from that state. + * + * @note + * Calling XXH32_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH32_hash_t. + */ +typedef struct { + unsigned char digest[4]; /*!< Hash bytes, big endian */ +} XXH32_canonical_t; + +/*! + * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. + * + * @param dst The @ref XXH32_canonical_t pointer to be stored to. + * @param hash The @ref XXH32_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); + +/*! + * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. + * + * @param src The @ref XXH32_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + + +/*! @cond Doxygen ignores this part */ +#ifdef __has_attribute +# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define XXH_HAS_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * C23 __STDC_VERSION__ number hasn't been specified yet. For now + * leave as `201711L` (C17 + 1). + * TODO: Update to correct value when its been specified. + */ +#define XXH_C23_VN 201711L +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* C-language Attributes are added in C23. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) +# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) +#else +# define XXH_HAS_C_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +#if defined(__cplusplus) && defined(__has_cpp_attribute) +# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define XXH_HAS_CPP_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute + * introduced in CPP17 and C23. + * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough + * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough + */ +#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) +# define XXH_FALLTHROUGH [[fallthrough]] +#elif XXH_HAS_ATTRIBUTE(__fallthrough__) +# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) +#else +# define XXH_FALLTHROUGH /* fallthrough */ +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_NOESCAPE for annotated pointers in public API. + * https://clang.llvm.org/docs/AttributeReference.html#noescape + * As of writing this, only supported by clang. + */ +#if XXH_HAS_ATTRIBUTE(noescape) +# define XXH_NOESCAPE __attribute__((noescape)) +#else +# define XXH_NOESCAPE +#endif +/*! @endcond */ + + +/*! + * @} + * @ingroup public + * @{ + */ + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* don't include */ +/*! + * @brief An unsigned 64-bit integer. + * + * Not necessarily defined to `uint64_t` but functionally equivalent. + */ +typedef uint64_t XXH64_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint64_t XXH64_hash_t; +#else +# include +# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL + /* LP64 ABI says uint64_t is unsigned long */ + typedef unsigned long XXH64_hash_t; +# else + /* the following type must have a width of 64-bit */ + typedef unsigned long long XXH64_hash_t; +# endif +#endif + +/*! + * @} + * + * @defgroup XXH64_family XXH64 family + * @ingroup public + * @{ + * Contains functions used in the classic 64-bit xxHash algorithm. + * + * @note + * XXH3 provides competitive speed for both 32-bit and 64-bit systems, + * and offers true 64/128 bit hash results. + * It provides better speed for systems with vector processing capabilities. + */ + +/*! + * @brief Calculates the 64-bit hash of @p input using xxHash64. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit xxHash64 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/*! + * @brief The opaque state struct for the XXH64 streaming API. + * + * @see XXH64_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ + +/*! + * @brief Allocates an @ref XXH64_state_t. + * + * @return An allocated pointer of @ref XXH64_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH64_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); + +/*! + * @brief Frees an @ref XXH64_state_t. + * + * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH64_createState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH64_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +/*! + * @brief Resets an @ref XXH64_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH64_update(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH64_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH64_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 64-bit xxHash64 value from that state. + * + * @note + * Calling XXH64_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ +/******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH64_hash_t. + */ +typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; + +/*! + * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. + * + * @param dst The @ref XXH64_canonical_t pointer to be stored to. + * @param hash The @ref XXH64_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); + +/*! + * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. + * + * @param src The @ref XXH64_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); + +#ifndef XXH_NO_XXH3 + +/*! + * @} + * ************************************************************************ + * @defgroup XXH3_family XXH3 family + * @ingroup public + * @{ + * + * XXH3 is a more recent hash algorithm featuring: + * - Improved speed for both small and large inputs + * - True 64-bit and 128-bit outputs + * - SIMD acceleration + * - Improved 32-bit viability + * + * Speed analysis methodology is explained here: + * + * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html + * + * Compared to XXH64, expect XXH3 to run approximately + * ~2x faster on large inputs and >3x faster on small ones, + * exact differences vary depending on platform. + * + * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, + * but does not require it. + * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 + * at competitive speeds, even without vector support. Further details are + * explained in the implementation. + * + * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD + * implementations for many common platforms: + * - AVX512 + * - AVX2 + * - SSE2 + * - ARM NEON + * - WebAssembly SIMD128 + * - POWER8 VSX + * - s390x ZVector + * This can be controlled via the @ref XXH_VECTOR macro, but it automatically + * selects the best version according to predefined macros. For the x86 family, an + * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. + * + * XXH3 implementation is portable: + * it has a generic C90 formulation that can be compiled on any platform, + * all implementations generate exactly the same hash value on all platforms. + * Starting from v0.8.0, it's also labelled "stable", meaning that + * any future version will also generate the same hash value. + * + * XXH3 offers 2 variants, _64bits and _128bits. + * + * When only 64 bits are needed, prefer invoking the _64bits variant, as it + * reduces the amount of mixing, resulting in faster speed on small inputs. + * It's also generally simpler to manipulate a scalar return type than a struct. + * + * The API supports one-shot hashing, streaming mode, and custom secrets. + */ +/*-********************************************************************** +* XXH3 64-bit variant +************************************************************************/ + +/*! + * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see + * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/*! + * The bare minimum size for a custom secret. + * + * @see + * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), + * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). + */ +#define XXH3_SECRET_SIZE_MIN 136 + +/*! + * @brief Calculates 64-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + */ + +/*! + * @brief The opaque state struct for the XXH3 streaming API. + * + * @see XXH3_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH3_state_s XXH3_state_t; +XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH3_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits()`. + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * `secret` is referenced, it _must outlive_ the hash streaming session. + * + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 64-bit hash value from that state. + * + * @note + * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* note : canonical representation of XXH3 is the same as XXH64 + * since they both produce XXH64_hash_t values */ + + +/*-********************************************************************** +* XXH3 128-bit variant +************************************************************************/ + +/*! + * @brief The return value from 128-bit hashes. + * + * Stored in little endian order, although the fields themselves are in native + * endianness. + */ +typedef struct { + XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ + XXH64_hash_t high64; /*!< `value >> 64` */ +} XXH128_hash_t; + +/*! + * @brief Calculates 128-bit unseeded variant of XXH3 of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead + * for shorter inputs. + * + * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); +/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); +/*! + * @brief Calculates 128-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + * + * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). + * Use already declared XXH3_createState() and XXH3_freeState(). + * + * All reset and streaming functions have same meaning as their 64-bit counterpart. + */ + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits()`. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * `secret` is referenced, it _must outlive_ the hash streaming session. + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 128-bit hash value from that state. + * + * @note + * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* Following helper functions make it possible to compare XXH128_hast_t values. + * Since XXH128_hash_t is a structure, this capability is not offered by the language. + * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ + +/*! + * @brief Check equality of two XXH128_hash_t values + * + * @param h1 The 128-bit hash value. + * @param h2 Another 128-bit hash value. + * + * @return `1` if `h1` and `h2` are equal. + * @return `0` if they are not. + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); + +/*! + * @brief Compares two @ref XXH128_hash_t + * + * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. + * + * @param h128_1 Left-hand side value + * @param h128_2 Right-hand side value + * + * @return >0 if @p h128_1 > @p h128_2 + * @return =0 if @p h128_1 == @p h128_2 + * @return <0 if @p h128_1 < @p h128_2 + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); + + +/******* Canonical representation *******/ +typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; + + +/*! + * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. + * + * @param dst The @ref XXH128_canonical_t pointer to be stored to. + * @param hash The @ref XXH128_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); + +/*! + * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. + * + * @param src The @ref XXH128_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); + + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ + +/*! + * @} + */ +#endif /* XXHASH_H_5627135585666179 */ + + + +#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) +#define XXHASH_H_STATIC_13879238742 +/* **************************************************************************** + * This section contains declarations which are not guaranteed to remain stable. + * They may change in future versions, becoming incompatible with a different + * version of the library. + * These declarations should only be used with static linking. + * Never use them in association with dynamic linking! + ***************************************************************************** */ + +/* + * These definitions are only present to allow static allocation + * of XXH states, on stack or in a struct, for example. + * Never **ever** access their members directly. + */ + +/*! + * @internal + * @brief Structure for XXH32 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH32_state_t. + * Do not access the members of this struct directly. + * @see XXH64_state_s, XXH3_state_s + */ +struct XXH32_state_s { + XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ + XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ + XXH32_hash_t v[4]; /*!< Accumulator lanes */ + XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ + XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ +}; /* typedef'd to XXH32_state_t */ + + +#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ + +/*! + * @internal + * @brief Structure for XXH64 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH64_state_t. + * Do not access the members of this struct directly. + * @see XXH32_state_s, XXH3_state_s + */ +struct XXH64_state_s { + XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ + XXH64_hash_t v[4]; /*!< Accumulator lanes */ + XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ + XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ + XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ +}; /* typedef'd to XXH64_state_t */ + +#ifndef XXH_NO_XXH3 + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ +# include +# define XXH_ALIGN(n) alignas(n) +#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ +/* In C++ alignas() is a keyword */ +# define XXH_ALIGN(n) alignas(n) +#elif defined(__GNUC__) +# define XXH_ALIGN(n) __attribute__ ((aligned(n))) +#elif defined(_MSC_VER) +# define XXH_ALIGN(n) __declspec(align(n)) +#else +# define XXH_ALIGN(n) /* disabled */ +#endif + +/* Old GCC versions only accept the attribute after the type in structures. */ +#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ + && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ + && defined(__GNUC__) +# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) +#else +# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type +#endif + +/*! + * @brief The size of the internal XXH3 buffer. + * + * This is the optimal update size for incremental hashing. + * + * @see XXH3_64b_update(), XXH3_128b_update(). + */ +#define XXH3_INTERNALBUFFER_SIZE 256 + +/*! + * @internal + * @brief Default size of the secret buffer (and @ref XXH3_kSecret). + * + * This is the size used in @ref XXH3_kSecret and the seeded functions. + * + * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. + */ +#define XXH3_SECRET_DEFAULT_SIZE 192 + +/*! + * @internal + * @brief Structure for XXH3 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. + * Otherwise it is an opaque type. + * Never use this definition in combination with dynamic library. + * This allows fields to safely be changed in the future. + * + * @note ** This structure has a strict alignment requirement of 64 bytes!! ** + * Do not allocate this with `malloc()` or `new`, + * it will not be sufficiently aligned. + * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. + * + * Typedef'd to @ref XXH3_state_t. + * Do never access the members of this struct directly. + * + * @see XXH3_INITSTATE() for stack initialization. + * @see XXH3_createState(), XXH3_freeState(). + * @see XXH32_state_s, XXH64_state_s + */ +struct XXH3_state_s { + XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); + /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ + XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); + /*!< Used to store a custom secret generated from a seed. */ + XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); + /*!< The internal buffer. @see XXH32_state_s::mem32 */ + XXH32_hash_t bufferedSize; + /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ + XXH32_hash_t useSeed; + /*!< Reserved field. Needed for padding on 64-bit. */ + size_t nbStripesSoFar; + /*!< Number or stripes processed. */ + XXH64_hash_t totalLen; + /*!< Total length hashed. 64-bit even on 32-bit targets. */ + size_t nbStripesPerBlock; + /*!< Number of stripes per block. */ + size_t secretLimit; + /*!< Size of @ref customSecret or @ref extSecret */ + XXH64_hash_t seed; + /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ + XXH64_hash_t reserved64; + /*!< Reserved field. */ + const unsigned char* extSecret; + /*!< Reference to an external secret for the _withSecret variants, NULL + * for other variants. */ + /* note: there may be some padding at the end due to alignment on 64 bytes */ +}; /* typedef'd to XXH3_state_t */ + +#undef XXH_ALIGN_MEMBER + +/*! + * @brief Initializes a stack-allocated `XXH3_state_s`. + * + * When the @ref XXH3_state_t structure is merely emplaced on stack, + * it should be initialized with XXH3_INITSTATE() or a memset() + * in case its first reset uses XXH3_NNbits_reset_withSeed(). + * This init can be omitted if the first reset uses default or _withSecret mode. + * This operation isn't necessary when the state is created with XXH3_createState(). + * Note that this doesn't prepare the state for a streaming operation, + * it's still necessary to use XXH3_NNbits_reset*() afterwards. + */ +#define XXH3_INITSTATE(XXH3_state_ptr) \ + do { \ + XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ + tmp_xxh3_state_ptr->seed = 0; \ + tmp_xxh3_state_ptr->extSecret = NULL; \ + } while(0) + + +/*! + * @brief Calculates the 128-bit hash of @p data using XXH3. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p len is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 128-bit XXH3 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); + + +/* === Experimental API === */ +/* Symbols defined below must be considered tied to a specific library version. */ + +/*! + * @brief Derive a high-entropy secret from any user-defined content, named customSeed. + * + * @param secretBuffer A writable buffer for derived high-entropy secret data. + * @param secretSize Size of secretBuffer, in bytes. Must be >= XXH3_SECRET_DEFAULT_SIZE. + * @param customSeed A user-defined content. + * @param customSeedSize Size of customSeed, in bytes. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * The generated secret can be used in combination with `*_withSecret()` functions. + * The `_withSecret()` variants are useful to provide a higher level of protection + * than 64-bit seed, as it becomes much more difficult for an external actor to + * guess how to impact the calculation logic. + * + * The function accepts as input a custom seed of any length and any content, + * and derives from it a high-entropy secret of length @p secretSize into an + * already allocated buffer @p secretBuffer. + * + * The generated secret can then be used with any `*_withSecret()` variant. + * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), + * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() + * are part of this list. They all accept a `secret` parameter + * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) + * _and_ feature very high entropy (consist of random-looking bytes). + * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can + * be employed to ensure proper quality. + * + * @p customSeed can be anything. It can have any size, even small ones, + * and its content can be anything, even "poor entropy" sources such as a bunch + * of zeroes. The resulting `secret` will nonetheless provide all required qualities. + * + * @pre + * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN + * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. + * + * Example code: + * @code{.c} + * #include + * #include + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Hashes argv[2] using the entropy from argv[1]. + * int main(int argc, char* argv[]) + * { + * char secret[XXH3_SECRET_SIZE_MIN]; + * if (argv != 3) { return 1; } + * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); + * XXH64_hash_t h = XXH3_64bits_withSecret( + * argv[2], strlen(argv[2]), + * secret, sizeof(secret) + * ); + * printf("%016llx\n", (unsigned long long) h); + * } + * @endcode + */ +XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); + +/*! + * @brief Generate the same secret as the _withSeed() variants. + * + * @param secretBuffer A writable buffer of @ref XXH3_SECRET_SIZE_MIN bytes + * @param seed The 64-bit seed to alter the hash result predictably. + * + * The generated secret can be used in combination with + *`*_withSecret()` and `_withSecretandSeed()` variants. + * + * Example C++ `std::string` hash class: + * @code{.cpp} + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Slow, seeds each time + * class HashSlow { + * XXH64_hash_t seed; + * public: + * HashSlow(XXH64_hash_t s) : seed{s} {} + * size_t operator()(const std::string& x) const { + * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; + * } + * }; + * // Fast, caches the seeded secret for future uses. + * class HashFast { + * unsigned char secret[XXH3_SECRET_SIZE_MIN]; + * public: + * HashFast(XXH64_hash_t s) { + * XXH3_generateSecret_fromSeed(secret, seed); + * } + * size_t operator()(const std::string& x) const { + * return size_t{ + * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) + * }; + * } + * }; + * @endcode + */ +XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); + +/*! + * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * These variants generate hash values using either + * @p seed for "short" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes) + * or @p secret for "large" keys (>= @ref XXH3_MIDSIZE_MAX). + * + * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. + * `_withSeed()` has to generate the secret on the fly for "large" keys. + * It's fast, but can be perceptible for "not so large" keys (< 1 KB). + * `_withSecret()` has to generate the masks on the fly for "small" keys, + * which requires more instructions than _withSeed() variants. + * Therefore, _withSecretandSeed variant combines the best of both worlds. + * + * When @p secret has been generated by XXH3_generateSecret_fromSeed(), + * this variant produces *exactly* the same results as `_withSeed()` variant, + * hence offering only a pure speed benefit on "large" input, + * by skipping the need to regenerate the secret for every large input. + * + * Another usage scenario is to hash the secret to a 64-bit hash value, + * for example with XXH3_64bits(), which then becomes the seed, + * and then employ both the seed and the secret in _withSecretandSeed(). + * On top of speed, an added benefit is that each bit in the secret + * has a 50% chance to swap each bit in the output, via its impact to the seed. + * + * This is not guaranteed when using the secret directly in "small data" scenarios, + * because only portions of the secret are employed for small data. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed); +/*! + * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param input The block of data to be hashed, at least @p len bytes in size. + * @param length The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +#ifndef XXH_NO_STREAM +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed() + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); +#endif /* !XXH_NO_STREAM */ + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# define XXH_IMPLEMENTATION +#endif + +#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ + + +/* ======================================================================== */ +/* ======================================================================== */ +/* ======================================================================== */ + + +/*-********************************************************************** + * xxHash implementation + *-********************************************************************** + * xxHash's implementation used to be hosted inside xxhash.c. + * + * However, inlining requires implementation to be visible to the compiler, + * hence be included alongside the header. + * Previously, implementation was hosted inside xxhash.c, + * which was then #included when inlining was activated. + * This construction created issues with a few build and install systems, + * as it required xxhash.c to be stored in /include directory. + * + * xxHash implementation is now directly integrated within xxhash.h. + * As a consequence, xxhash.c is no longer needed in /include. + * + * xxhash.c is still available and is still useful. + * In a "normal" setup, when xxhash is not inlined, + * xxhash.h only exposes the prototypes and public symbols, + * while xxhash.c can be built into an object file xxhash.o + * which can then be linked into the final binary. + ************************************************************************/ + +#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ + || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) +# define XXH_IMPLEM_13a8737387 + +/* ************************************* +* Tuning parameters +***************************************/ + +/*! + * @defgroup tuning Tuning parameters + * @{ + * + * Various macros to control xxHash's behavior. + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Define this to disable 64-bit code. + * + * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. + */ +# define XXH_NO_LONG_LONG +# undef XXH_NO_LONG_LONG /* don't actually */ +/*! + * @brief Controls how unaligned memory is accessed. + * + * By default, access to unaligned memory is controlled by `memcpy()`, which is + * safe and portable. + * + * Unfortunately, on some target/compiler combinations, the generated assembly + * is sub-optimal. + * + * The below switch allow selection of a different access method + * in the search for improved performance. + * + * @par Possible options: + * + * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` + * @par + * Use `memcpy()`. Safe and portable. Note that most modern compilers will + * eliminate the function call and treat it as an unaligned access. + * + * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` + * @par + * Depends on compiler extensions and is therefore not portable. + * This method is safe _if_ your compiler supports it, + * and *generally* as fast or faster than `memcpy`. + * + * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast + * @par + * Casts directly and dereferences. This method doesn't depend on the + * compiler, but it violates the C standard as it directly dereferences an + * unaligned pointer. It can generate buggy code on targets which do not + * support unaligned memory accesses, but in some circumstances, it's the + * only known way to get the most performance. + * + * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift + * @par + * Also portable. This can generate the best code on old compilers which don't + * inline small `memcpy()` calls, and it might also be faster on big-endian + * systems which lack a native byteswap instruction. However, some compilers + * will emit literal byteshifts even if the target supports unaligned access. + * + * + * @warning + * Methods 1 and 2 rely on implementation-defined behavior. Use these with + * care, as what works on one compiler/platform/optimization level may cause + * another to read garbage data or even crash. + * + * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. + * + * Prefer these methods in priority order (0 > 3 > 1 > 2) + */ +# define XXH_FORCE_MEMORY_ACCESS 0 + +/*! + * @def XXH_SIZE_OPT + * @brief Controls how much xxHash optimizes for size. + * + * xxHash, when compiled, tends to result in a rather large binary size. This + * is mostly due to heavy usage to forced inlining and constant folding of the + * @ref XXH3_family to increase performance. + * + * However, some developers prefer size over speed. This option can + * significantly reduce the size of the generated code. When using the `-Os` + * or `-Oz` options on GCC or Clang, this is defined to 1 by default, + * otherwise it is defined to 0. + * + * Most of these size optimizations can be controlled manually. + * + * This is a number from 0-2. + * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed + * comes first. + * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more + * conservative and disables hacks that increase code size. It implies the + * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, + * and @ref XXH3_NEON_LANES == 8 if they are not already defined. + * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. + * Performance may cry. For example, the single shot functions just use the + * streaming API. + */ +# define XXH_SIZE_OPT 0 + +/*! + * @def XXH_FORCE_ALIGN_CHECK + * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() + * and XXH64() only). + * + * This is an important performance trick for architectures without decent + * unaligned memory access performance. + * + * It checks for input alignment, and when conditions are met, uses a "fast + * path" employing direct 32-bit/64-bit reads, resulting in _dramatically + * faster_ read speed. + * + * The check costs one initial branch per hash, which is generally negligible, + * but not zero. + * + * Moreover, it's not useful to generate an additional code path if memory + * access uses the same instruction for both aligned and unaligned + * addresses (e.g. x86 and aarch64). + * + * In these cases, the alignment check can be removed by setting this macro to 0. + * Then the code will always use unaligned memory access. + * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips + * which are platforms known to offer good unaligned memory accesses performance. + * + * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. + * + * This option does not affect XXH3 (only XXH32 and XXH64). + */ +# define XXH_FORCE_ALIGN_CHECK 0 + +/*! + * @def XXH_NO_INLINE_HINTS + * @brief When non-zero, sets all functions to `static`. + * + * By default, xxHash tries to force the compiler to inline almost all internal + * functions. + * + * This can usually improve performance due to reduced jumping and improved + * constant folding, but significantly increases the size of the binary which + * might not be favorable. + * + * Additionally, sometimes the forced inlining can be detrimental to performance, + * depending on the architecture. + * + * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the + * compiler full control on whether to inline or not. + * + * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if + * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. + */ +# define XXH_NO_INLINE_HINTS 0 + +/*! + * @def XXH3_INLINE_SECRET + * @brief Determines whether to inline the XXH3 withSecret code. + * + * When the secret size is known, the compiler can improve the performance + * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret(). + * + * However, if the secret size is not known, it doesn't have any benefit. This + * happens when xxHash is compiled into a global symbol. Therefore, if + * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0. + * + * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers + * that are *sometimes* force inline on -Og, and it is impossible to automatically + * detect this optimization level. + */ +# define XXH3_INLINE_SECRET 0 + +/*! + * @def XXH32_ENDJMP + * @brief Whether to use a jump for `XXH32_finalize`. + * + * For performance, `XXH32_finalize` uses multiple branches in the finalizer. + * This is generally preferable for performance, + * but depending on exact architecture, a jmp may be preferable. + * + * This setting is only possibly making a difference for very small inputs. + */ +# define XXH32_ENDJMP 0 + +/*! + * @internal + * @brief Redefines old internal names. + * + * For compatibility with code that uses xxHash's internals before the names + * were changed to improve namespacing. There is no other reason to use this. + */ +# define XXH_OLD_NAMES +# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ + +/*! + * @def XXH_NO_STREAM + * @brief Disables the streaming API. + * + * When xxHash is not inlined and the streaming functions are not used, disabling + * the streaming functions can improve code size significantly, especially with + * the @ref XXH3_family which tends to make constant folded copies of itself. + */ +# define XXH_NO_STREAM +# undef XXH_NO_STREAM /* don't actually */ +#endif /* XXH_DOXYGEN */ +/*! + * @} + */ + +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ + /* prefer __packed__ structures (method 1) for GCC + * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy + * which for some reason does unaligned loads. */ +# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +#ifndef XXH_SIZE_OPT + /* default to 1 for -Os or -Oz */ +# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) +# define XXH_SIZE_OPT 1 +# else +# define XXH_SIZE_OPT 0 +# endif +#endif + +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ + /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ +# if XXH_SIZE_OPT >= 1 || \ + defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ + || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + +#ifndef XXH_NO_INLINE_HINTS +# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ +# define XXH_NO_INLINE_HINTS 1 +# else +# define XXH_NO_INLINE_HINTS 0 +# endif +#endif + +#ifndef XXH3_INLINE_SECRET +# if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \ + || !defined(XXH_INLINE_ALL) +# define XXH3_INLINE_SECRET 0 +# else +# define XXH3_INLINE_SECRET 1 +# endif +#endif + +#ifndef XXH32_ENDJMP +/* generally preferable for performance */ +# define XXH32_ENDJMP 0 +#endif + +/*! + * @defgroup impl Implementation + * @{ + */ + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +#if defined(XXH_NO_STREAM) +/* nothing */ +#elif defined(XXH_NO_STDLIB) + +/* When requesting to disable any mention of stdlib, + * the library loses the ability to invoked malloc / free. + * In practice, it means that functions like `XXH*_createState()` + * will always fail, and return NULL. + * This flag is useful in situations where + * xxhash.h is integrated into some kernel, embedded or limited environment + * without access to dynamic allocation. + */ + +static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } +static void XXH_free(void* p) { (void)p; } + +#else + +/* + * Modify the local functions below should you wish to use + * different memory routines for malloc() and free() + */ +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than malloc(). + */ +static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } + +/*! + * @internal + * @brief Modify this function to use a different routine than free(). + */ +static void XXH_free(void* p) { free(p); } + +#endif /* XXH_NO_STDLIB */ + +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than memcpy(). + */ +static void* XXH_memcpy(void* dest, const void* src, size_t size) +{ + return memcpy(dest,src,size); +} + +#include /* ULLONG_MAX */ + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio warning fix */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + +#if XXH_NO_INLINE_HINTS /* disable inlining hints */ +# if defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __attribute__((unused)) +# else +# define XXH_FORCE_INLINE static +# endif +# define XXH_NO_INLINE static +/* enable inlining hints */ +#elif defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) +# define XXH_NO_INLINE static __attribute__((noinline)) +#elif defined(_MSC_VER) /* Visual Studio */ +# define XXH_FORCE_INLINE static __forceinline +# define XXH_NO_INLINE static __declspec(noinline) +#elif defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ +# define XXH_FORCE_INLINE static inline +# define XXH_NO_INLINE static +#else +# define XXH_FORCE_INLINE static +# define XXH_NO_INLINE static +#endif + +#if XXH3_INLINE_SECRET +# define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE +#else +# define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE +#endif + + +/* ************************************* +* Debug +***************************************/ +/*! + * @ingroup tuning + * @def XXH_DEBUGLEVEL + * @brief Sets the debugging level. + * + * XXH_DEBUGLEVEL is expected to be defined externally, typically via the + * compiler's command line options. The value must be a number. + */ +#ifndef XXH_DEBUGLEVEL +# ifdef DEBUGLEVEL /* backwards compat */ +# define XXH_DEBUGLEVEL DEBUGLEVEL +# else +# define XXH_DEBUGLEVEL 0 +# endif +#endif + +#if (XXH_DEBUGLEVEL>=1) +# include /* note: can still be disabled with NDEBUG */ +# define XXH_ASSERT(c) assert(c) +#else +# if defined(__INTEL_COMPILER) +# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) +# else +# define XXH_ASSERT(c) XXH_ASSUME(c) +# endif +#endif + +/* note: use after variable declarations */ +#ifndef XXH_STATIC_ASSERT +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) +# elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) +# else +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) +# endif +# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) +#endif + +/*! + * @internal + * @def XXH_COMPILER_GUARD(var) + * @brief Used to prevent unwanted optimizations for @p var. + * + * It uses an empty GCC inline assembly statement with a register constraint + * which forces @p var into a general purpose register (eg eax, ebx, ecx + * on x86) and marks it as modified. + * + * This is used in a few places to avoid unwanted autovectorization (e.g. + * XXH32_round()). All vectorization we want is explicit via intrinsics, + * and _usually_ isn't wanted elsewhere. + * + * We also use it to prevent unwanted constant folding for AArch64 in + * XXH3_initCustomSecret_scalar(). + */ +#if defined(__GNUC__) || defined(__clang__) +# define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) +#else +# define XXH_COMPILER_GUARD(var) ((void)0) +#endif + +/* Specifically for NEON vectors which use the "w" constraint, on + * Clang. */ +#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) +# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) +#else +# define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) +#endif + +/* ************************************* +* Basic Types +***************************************/ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint8_t xxh_u8; +#else + typedef unsigned char xxh_u8; +#endif +typedef XXH32_hash_t xxh_u32; + +#ifdef XXH_OLD_NAMES +# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" +# define BYTE xxh_u8 +# define U8 xxh_u8 +# define U32 xxh_u32 +#endif + +/* *** Memory access *** */ + +/*! + * @internal + * @fn xxh_u32 XXH_read32(const void* ptr) + * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit native endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32(const void* ptr) + * @brief Reads an unaligned 32-bit little endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readBE32(const void* ptr) + * @brief Reads an unaligned 32-bit big endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit big endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) + * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is + * always @ref XXH_alignment::XXH_unaligned. + * + * @param ptr The pointer to read from. + * @param align Whether @p ptr is aligned. + * @pre + * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte + * aligned. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE32 and XXH_readBE32. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* + * Force direct memory access. Only works on CPU which support unaligned memory + * access in hardware. + */ +static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; +#endif +static xxh_u32 XXH_read32(const void* ptr) +{ + typedef __attribute__((aligned(1))) xxh_u32 xxh_unalign32; + return *((const xxh_unalign32*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u32 XXH_read32(const void* memPtr) +{ + xxh_u32 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* *** Endianness *** */ + +/*! + * @ingroup tuning + * @def XXH_CPU_LITTLE_ENDIAN + * @brief Whether the target is little endian. + * + * Defined to 1 if the target is little endian, or 0 if it is big endian. + * It can be defined externally, for example on the compiler command line. + * + * If it is not defined, + * a runtime check (which is usually constant folded) is used instead. + * + * @note + * This is not necessarily defined to an integer constant. + * + * @see XXH_isLittleEndian() for the runtime check. + */ +#ifndef XXH_CPU_LITTLE_ENDIAN +/* + * Try to detect endianness automatically, to avoid the nonstandard behavior + * in `XXH_isLittleEndian()` + */ +# if defined(_WIN32) /* Windows is always little endian */ \ + || defined(__LITTLE_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 1 +# elif defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 0 +# else +/*! + * @internal + * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. + * + * Most compilers will constant fold this. + */ +static int XXH_isLittleEndian(void) +{ + /* + * Portable and well-defined behavior. + * Don't use static: it is detrimental to performance. + */ + const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; + return one.c[0]; +} +# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() +# endif +#endif + + + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef __has_builtin +# define XXH_HAS_BUILTIN(x) __has_builtin(x) +#else +# define XXH_HAS_BUILTIN(x) 0 +#endif + + + +/* + * C23 and future versions have standard "unreachable()". + * Once it has been implemented reliably we can add it as an + * additional case: + * + * ``` + * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) + * # include + * # ifdef unreachable + * # define XXH_UNREACHABLE() unreachable() + * # endif + * #endif + * ``` + * + * Note C++23 also has std::unreachable() which can be detected + * as follows: + * ``` + * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) + * # include + * # define XXH_UNREACHABLE() std::unreachable() + * #endif + * ``` + * NB: `__cpp_lib_unreachable` is defined in the `` header. + * We don't use that as including `` in `extern "C"` blocks + * doesn't work on GCC12 + */ + +#if XXH_HAS_BUILTIN(__builtin_unreachable) +# define XXH_UNREACHABLE() __builtin_unreachable() + +#elif defined(_MSC_VER) +# define XXH_UNREACHABLE() __assume(0) + +#else +# define XXH_UNREACHABLE() +#endif + +#if XXH_HAS_BUILTIN(__builtin_assume) +# define XXH_ASSUME(c) __builtin_assume(c) +#else +# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } +#endif + +/*! + * @internal + * @def XXH_rotl32(x,r) + * @brief 32-bit rotate left. + * + * @param x The 32-bit integer to be rotated. + * @param r The number of bits to rotate. + * @pre + * @p r > 0 && @p r < 32 + * @note + * @p x and @p r may be evaluated multiple times. + * @return The rotated result. + */ +#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ + && XXH_HAS_BUILTIN(__builtin_rotateleft64) +# define XXH_rotl32 __builtin_rotateleft32 +# define XXH_rotl64 __builtin_rotateleft64 +/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ +#elif defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) +#endif + +/*! + * @internal + * @fn xxh_u32 XXH_swap32(xxh_u32 x) + * @brief A 32-bit byteswap. + * + * @param x The 32-bit integer to byteswap. + * @return @p x, byteswapped. + */ +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static xxh_u32 XXH_swap32 (xxh_u32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* *************************** +* Memory reads +*****************************/ + +/*! + * @internal + * @brief Enum to indicate whether a pointer is aligned. + */ +typedef enum { + XXH_aligned, /*!< Aligned */ + XXH_unaligned /*!< Possibly unaligned */ +} XXH_alignment; + +/* + * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. + * + * This is ideal for older compilers which don't inline memcpy. + */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u32)bytePtr[1] << 8) + | ((xxh_u32)bytePtr[2] << 16) + | ((xxh_u32)bytePtr[3] << 24); +} + +XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[3] + | ((xxh_u32)bytePtr[2] << 8) + | ((xxh_u32)bytePtr[1] << 16) + | ((xxh_u32)bytePtr[0] << 24); +} + +#else +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); +} + +static xxh_u32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u32 +XXH_readLE32_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) { + return XXH_readLE32(ptr); + } else { + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); + } +} + + +/* ************************************* +* Misc +***************************************/ +/*! @ingroup public */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +/*! + * @} + * @defgroup XXH32_impl XXH32 implementation + * @ingroup impl + * + * Details on the XXH32 implementation. + * @{ + */ + /* #define instead of static const, to be used as initializers */ +#define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ +#define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ +#define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ +#define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ +#define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ + +#ifdef XXH_OLD_NAMES +# define PRIME32_1 XXH_PRIME32_1 +# define PRIME32_2 XXH_PRIME32_2 +# define PRIME32_3 XXH_PRIME32_3 +# define PRIME32_4 XXH_PRIME32_4 +# define PRIME32_5 XXH_PRIME32_5 +#endif + +/*! + * @internal + * @brief Normal stripe processing routine. + * + * This shuffles the bits so that any bit from @p input impacts several bits in + * @p acc. + * + * @param acc The accumulator lane. + * @param input The stripe of input to mix. + * @return The mixed accumulator lane. + */ +static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) +{ + acc += input * XXH_PRIME32_2; + acc = XXH_rotl32(acc, 13); + acc *= XXH_PRIME32_1; +#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * UGLY HACK: + * A compiler fence is the only thing that prevents GCC and Clang from + * autovectorizing the XXH32 loop (pragmas and attributes don't work for some + * reason) without globally disabling SSE4.1. + * + * The reason we want to avoid vectorization is because despite working on + * 4 integers at a time, there are multiple factors slowing XXH32 down on + * SSE4: + * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on + * newer chips!) making it slightly slower to multiply four integers at + * once compared to four integers independently. Even when pmulld was + * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE + * just to multiply unless doing a long operation. + * + * - Four instructions are required to rotate, + * movqda tmp, v // not required with VEX encoding + * pslld tmp, 13 // tmp <<= 13 + * psrld v, 19 // x >>= 19 + * por v, tmp // x |= tmp + * compared to one for scalar: + * roll v, 13 // reliably fast across the board + * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason + * + * - Instruction level parallelism is actually more beneficial here because + * the SIMD actually serializes this operation: While v1 is rotating, v2 + * can load data, while v3 can multiply. SSE forces them to operate + * together. + * + * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing + * the loop. NEON is only faster on the A53, and with the newer cores, it is less + * than half the speed. + * + * Additionally, this is used on WASM SIMD128 because it JITs to the same + * SIMD instructions and has the same issue. + */ + XXH_COMPILER_GUARD(acc); +#endif + return acc; +} + +/*! + * @internal + * @brief Mixes all bits to finalize the hash. + * + * The final mix ensures that all input bits have a chance to impact any bit in + * the output digest, resulting in an unbiased distribution. + * + * @param hash The hash to avalanche. + * @return The avalanched hash. + */ +static xxh_u32 XXH32_avalanche(xxh_u32 hash) +{ + hash ^= hash >> 15; + hash *= XXH_PRIME32_2; + hash ^= hash >> 13; + hash *= XXH_PRIME32_3; + hash ^= hash >> 16; + return hash; +} + +#define XXH_get32bits(p) XXH_readLE32_align(p, align) + +/*! + * @internal + * @brief Processes the last 0-15 bytes of @p ptr. + * + * There may be up to 15 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 16. + * @param align Whether @p ptr is aligned. + * @return The finalized hash. + * @see XXH64_finalize(). + */ +static XXH_PUREF xxh_u32 +XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ +#define XXH_PROCESS1 do { \ + hash += (*ptr++) * XXH_PRIME32_5; \ + hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ +} while (0) + +#define XXH_PROCESS4 do { \ + hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ + ptr += 4; \ + hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ +} while (0) + + if (ptr==NULL) XXH_ASSERT(len == 0); + + /* Compact rerolled version; generally faster */ + if (!XXH32_ENDJMP) { + len &= 15; + while (len >= 4) { + XXH_PROCESS4; + len -= 4; + } + while (len > 0) { + XXH_PROCESS1; + --len; + } + return XXH32_avalanche(hash); + } else { + switch(len&15) /* or switch(bEnd - p) */ { + case 12: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 8: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 4: XXH_PROCESS4; + return XXH32_avalanche(hash); + + case 13: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 9: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 5: XXH_PROCESS4; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 14: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 10: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 6: XXH_PROCESS4; + XXH_PROCESS1; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 15: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 11: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 7: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 3: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 2: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 1: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 0: return XXH32_avalanche(hash); + } + XXH_ASSERT(0); + return hash; /* reaching this point is deemed impossible */ + } +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1 XXH_PROCESS1 +# define PROCESS4 XXH_PROCESS4 +#else +# undef XXH_PROCESS1 +# undef XXH_PROCESS4 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH32(). + * + * @param input , len , seed Directly passed from @ref XXH32(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u32 +XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) +{ + xxh_u32 h32; + + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=16) { + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 15; + xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + xxh_u32 v2 = seed + XXH_PRIME32_2; + xxh_u32 v3 = seed + 0; + xxh_u32 v4 = seed - XXH_PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; + v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; + v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; + v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; + } while (input < limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + XXH_PRIME32_5; + } + + h32 += (xxh_u32)len; + + return XXH32_finalize(h32, input, len&15, align); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) +{ +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, (const xxh_u8*)input, len); + return XXH32_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); +#endif +} + + + +/******* Hash streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + statePtr->v[1] = seed + XXH_PRIME32_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME32_1; + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode +XXH32_update(XXH32_state_t* state, const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len_32 += (XXH32_hash_t)len; + state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); + state->memsize += (XXH32_hash_t)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const xxh_u32* p32 = state->mem32; + state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++; + state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++; + state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++; + state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const xxh_u8* const limit = bEnd - 16; + + do { + state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4; + state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4; + state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4; + state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4; + } while (p<=limit); + + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) +{ + xxh_u32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v[0], 1) + + XXH_rotl32(state->v[1], 7) + + XXH_rotl32(state->v[2], 12) + + XXH_rotl32(state->v[3], 18); + } else { + h32 = state->v[2] /* == seed */ + XXH_PRIME32_5; + } + + h32 += state->total_len_32; + + return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ +/*! + * @} + * @ingroup impl + * @{ + */ +/******* Memory access *******/ + +typedef XXH64_hash_t xxh_u64; + +#ifdef XXH_OLD_NAMES +# define U64 xxh_u64 +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE64 and XXH_readBE64. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + return *(const xxh_u64*) memPtr; +} + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; +#endif +static xxh_u64 XXH_read64(const void* ptr) +{ + typedef __attribute__((aligned(1))) xxh_u64 xxh_unalign64; + return *((const xxh_unalign64*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + xxh_u64 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static xxh_u64 XXH_swap64(xxh_u64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + + +/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u64)bytePtr[1] << 8) + | ((xxh_u64)bytePtr[2] << 16) + | ((xxh_u64)bytePtr[3] << 24) + | ((xxh_u64)bytePtr[4] << 32) + | ((xxh_u64)bytePtr[5] << 40) + | ((xxh_u64)bytePtr[6] << 48) + | ((xxh_u64)bytePtr[7] << 56); +} + +XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[7] + | ((xxh_u64)bytePtr[6] << 8) + | ((xxh_u64)bytePtr[5] << 16) + | ((xxh_u64)bytePtr[4] << 24) + | ((xxh_u64)bytePtr[3] << 32) + | ((xxh_u64)bytePtr[2] << 40) + | ((xxh_u64)bytePtr[1] << 48) + | ((xxh_u64)bytePtr[0] << 56); +} + +#else +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); +} + +static xxh_u64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u64 +XXH_readLE64_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) + return XXH_readLE64(ptr); + else + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); +} + + +/******* xxh64 *******/ +/*! + * @} + * @defgroup XXH64_impl XXH64 implementation + * @ingroup impl + * + * Details on the XXH64 implementation. + * @{ + */ +/* #define rather that static const, to be used as initializers */ +#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ +#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ +#define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ +#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ +#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ + +#ifdef XXH_OLD_NAMES +# define PRIME64_1 XXH_PRIME64_1 +# define PRIME64_2 XXH_PRIME64_2 +# define PRIME64_3 XXH_PRIME64_3 +# define PRIME64_4 XXH_PRIME64_4 +# define PRIME64_5 XXH_PRIME64_5 +#endif + +/*! @copydoc XXH32_round */ +static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) +{ + acc += input * XXH_PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= XXH_PRIME64_1; + return acc; +} + +static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; + return acc; +} + +/*! @copydoc XXH32_avalanche */ +static xxh_u64 XXH64_avalanche(xxh_u64 hash) +{ + hash ^= hash >> 33; + hash *= XXH_PRIME64_2; + hash ^= hash >> 29; + hash *= XXH_PRIME64_3; + hash ^= hash >> 32; + return hash; +} + + +#define XXH_get64bits(p) XXH_readLE64_align(p, align) + +/*! + * @internal + * @brief Processes the last 0-31 bytes of @p ptr. + * + * There may be up to 31 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 32. + * @param align Whether @p ptr is aligned. + * @return The finalized hash + * @see XXH32_finalize(). + */ +static XXH_PUREF xxh_u64 +XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ + if (ptr==NULL) XXH_ASSERT(len == 0); + len &= 31; + while (len >= 8) { + xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); + ptr += 8; + hash ^= k1; + hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; + len -= 8; + } + if (len >= 4) { + hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; + ptr += 4; + hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; + len -= 4; + } + while (len > 0) { + hash ^= (*ptr++) * XXH_PRIME64_5; + hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; + --len; + } + return XXH64_avalanche(hash); +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1_64 XXH_PROCESS1_64 +# define PROCESS4_64 XXH_PROCESS4_64 +# define PROCESS8_64 XXH_PROCESS8_64 +#else +# undef XXH_PROCESS1_64 +# undef XXH_PROCESS4_64 +# undef XXH_PROCESS8_64 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH64(). + * + * @param input , len , seed Directly passed from @ref XXH64(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 +XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) +{ + xxh_u64 h64; + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=32) { + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 31; + xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + xxh_u64 v2 = seed + XXH_PRIME64_2; + xxh_u64 v3 = seed + 0; + xxh_u64 v4 = seed - XXH_PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; + v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; + v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; + v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; + } while (input= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, (const xxh_u8*)input, len); + return XXH64_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); + +#endif +} + +/******* Hash Streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH64_family*/ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + statePtr->v[1] = seed + XXH_PRIME64_2; + statePtr->v[2] = seed + 0; + statePtr->v[3] = seed - XXH_PRIME64_1; + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode +XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); + state->memsize += (xxh_u32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0)); + state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1)); + state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2)); + state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3)); + p += 32 - state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const xxh_u8* const limit = bEnd - 32; + + do { + state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8; + state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8; + state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8; + state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8; + } while (p<=limit); + + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) +{ + xxh_u64 h64; + + if (state->total_len >= 32) { + h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18); + h64 = XXH64_mergeRound(h64, state->v[0]); + h64 = XXH64_mergeRound(h64, state->v[1]); + h64 = XXH64_mergeRound(h64, state->v[2]); + h64 = XXH64_mergeRound(h64, state->v[3]); + } else { + h64 = state->v[2] /*seed*/ + XXH_PRIME64_5; + } + + h64 += (xxh_u64) state->total_len; + + return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#ifndef XXH_NO_XXH3 + +/* ********************************************************************* +* XXH3 +* New generation hash designed for speed on small keys and vectorization +************************************************************************ */ +/*! + * @} + * @defgroup XXH3_impl XXH3 implementation + * @ingroup impl + * @{ + */ + +/* === Compiler specifics === */ + +#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ +# define XXH_RESTRICT /* disable */ +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ +# define XXH_RESTRICT restrict +#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ + || (defined (__clang__)) \ + || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ + || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) +/* + * There are a LOT more compilers that recognize __restrict but this + * covers the major ones. + */ +# define XXH_RESTRICT __restrict +#else +# define XXH_RESTRICT /* disable */ +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) \ + || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ + || defined(__clang__) +# define XXH_likely(x) __builtin_expect(x, 1) +# define XXH_unlikely(x) __builtin_expect(x, 0) +#else +# define XXH_likely(x) (x) +# define XXH_unlikely(x) (x) +#endif + +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# if defined(__ARM_FEATURE_SVE) +# include +# endif +# if defined(__ARM_NEON__) || defined(__ARM_NEON) \ + || (defined(_M_ARM) && _M_ARM >= 7) \ + || defined(_M_ARM64) || defined(_M_ARM64EC) \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ +# define inline __inline__ /* circumvent a clang bug */ +# include +# undef inline +# elif defined(__AVX2__) +# include +# elif defined(__SSE2__) +# include +# endif +#endif + +#if defined(_MSC_VER) +# include +#endif + +/* + * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while + * remaining a true 64-bit/128-bit hash function. + * + * This is done by prioritizing a subset of 64-bit operations that can be + * emulated without too many steps on the average 32-bit machine. + * + * For example, these two lines seem similar, and run equally fast on 64-bit: + * + * xxh_u64 x; + * x ^= (x >> 47); // good + * x ^= (x >> 13); // bad + * + * However, to a 32-bit machine, there is a major difference. + * + * x ^= (x >> 47) looks like this: + * + * x.lo ^= (x.hi >> (47 - 32)); + * + * while x ^= (x >> 13) looks like this: + * + * // note: funnel shifts are not usually cheap. + * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); + * x.hi ^= (x.hi >> 13); + * + * The first one is significantly faster than the second, simply because the + * shift is larger than 32. This means: + * - All the bits we need are in the upper 32 bits, so we can ignore the lower + * 32 bits in the shift. + * - The shift result will always fit in the lower 32 bits, and therefore, + * we can ignore the upper 32 bits in the xor. + * + * Thanks to this optimization, XXH3 only requires these features to be efficient: + * + * - Usable unaligned access + * - A 32-bit or 64-bit ALU + * - If 32-bit, a decent ADC instruction + * - A 32 or 64-bit multiply with a 64-bit result + * - For the 128-bit variant, a decent byteswap helps short inputs. + * + * The first two are already required by XXH32, and almost all 32-bit and 64-bit + * platforms which can run XXH32 can run XXH3 efficiently. + * + * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one + * notable exception. + * + * First of all, Thumb-1 lacks support for the UMULL instruction which + * performs the important long multiply. This means numerous __aeabi_lmul + * calls. + * + * Second of all, the 8 functional registers are just not enough. + * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need + * Lo registers, and this shuffling results in thousands more MOVs than A32. + * + * A32 and T32 don't have this limitation. They can access all 14 registers, + * do a 32->64 multiply with UMULL, and the flexible operand allowing free + * shifts is helpful, too. + * + * Therefore, we do a quick sanity check. + * + * If compiling Thumb-1 for a target which supports ARM instructions, we will + * emit a warning, as it is not a "sane" platform to compile for. + * + * Usually, if this happens, it is because of an accident and you probably need + * to specify -march, as you likely meant to compile for a newer architecture. + * + * Credit: large sections of the vectorial and asm source code paths + * have been contributed by @easyaspi314 + */ +#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) +# warning "XXH3 is highly inefficient without ARM or Thumb-2." +#endif + +/* ========================================== + * Vectorization detection + * ========================================== */ + +#ifdef XXH_DOXYGEN +/*! + * @ingroup tuning + * @brief Overrides the vectorization implementation chosen for XXH3. + * + * Can be defined to 0 to disable SIMD or any of the values mentioned in + * @ref XXH_VECTOR_TYPE. + * + * If this is not defined, it uses predefined macros to determine the best + * implementation. + */ +# define XXH_VECTOR XXH_SCALAR +/*! + * @ingroup tuning + * @brief Possible values for @ref XXH_VECTOR. + * + * Note that these are actually implemented as macros. + * + * If this is not defined, it is detected automatically. + * internal macro XXH_X86DISPATCH overrides this. + */ +enum XXH_VECTOR_TYPE /* fake enum */ { + XXH_SCALAR = 0, /*!< Portable scalar version */ + XXH_SSE2 = 1, /*!< + * SSE2 for Pentium 4, Opteron, all x86_64. + * + * @note SSE2 is also guaranteed on Windows 10, macOS, and + * Android x86. + */ + XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ + XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ + XXH_NEON = 4, /*!< + * NEON for most ARMv7-A, all AArch64, and WASM SIMD128 + * via the SIMDeverywhere polyfill provided with the + * Emscripten SDK. + */ + XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ + XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */ +}; +/*! + * @ingroup tuning + * @brief Selects the minimum alignment for XXH3's accumulators. + * + * When using SIMD, this should match the alignment required for said vector + * type, so, for example, 32 for AVX2. + * + * Default: Auto detected. + */ +# define XXH_ACC_ALIGN 8 +#endif + +/* Actual definition */ +#ifndef XXH_DOXYGEN +# define XXH_SCALAR 0 +# define XXH_SSE2 1 +# define XXH_AVX2 2 +# define XXH_AVX512 3 +# define XXH_NEON 4 +# define XXH_VSX 5 +# define XXH_SVE 6 +#endif + +#ifndef XXH_VECTOR /* can be defined on command line */ +# if defined(__ARM_FEATURE_SVE) +# define XXH_VECTOR XXH_SVE +# elif ( \ + defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ + || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ + ) && ( \ + defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ + ) +# define XXH_VECTOR XXH_NEON +# elif defined(__AVX512F__) +# define XXH_VECTOR XXH_AVX512 +# elif defined(__AVX2__) +# define XXH_VECTOR XXH_AVX2 +# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# define XXH_VECTOR XXH_SSE2 +# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ + || (defined(__s390x__) && defined(__VEC__)) \ + && defined(__GNUC__) /* TODO: IBM XL */ +# define XXH_VECTOR XXH_VSX +# else +# define XXH_VECTOR XXH_SCALAR +# endif +#endif + +/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ +#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) +# ifdef _MSC_VER +# pragma warning(once : 4606) +# else +# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." +# endif +# undef XXH_VECTOR +# define XXH_VECTOR XXH_SCALAR +#endif + +/* + * Controls the alignment of the accumulator, + * for compatibility with aligned vector loads, which are usually faster. + */ +#ifndef XXH_ACC_ALIGN +# if defined(XXH_X86DISPATCH) +# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ +# elif XXH_VECTOR == XXH_SCALAR /* scalar */ +# define XXH_ACC_ALIGN 8 +# elif XXH_VECTOR == XXH_SSE2 /* sse2 */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX2 /* avx2 */ +# define XXH_ACC_ALIGN 32 +# elif XXH_VECTOR == XXH_NEON /* neon */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_VSX /* vsx */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX512 /* avx512 */ +# define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_SVE /* sve */ +# define XXH_ACC_ALIGN 64 +# endif +#endif + +#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ + || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#elif XXH_VECTOR == XXH_SVE +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#else +# define XXH_SEC_ALIGN 8 +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define XXH_ALIASING __attribute__((may_alias)) +#else +# define XXH_ALIASING /* nothing */ +#endif + +/* + * UGLY HACK: + * GCC usually generates the best code with -O3 for xxHash. + * + * However, when targeting AVX2, it is overzealous in its unrolling resulting + * in code roughly 3/4 the speed of Clang. + * + * There are other issues, such as GCC splitting _mm256_loadu_si256 into + * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which + * only applies to Sandy and Ivy Bridge... which don't even support AVX2. + * + * That is why when compiling the AVX2 version, it is recommended to use either + * -O2 -mavx2 -march=haswell + * or + * -O2 -mavx2 -mno-avx256-split-unaligned-load + * for decent performance, or to use Clang instead. + * + * Fortunately, we can control the first one with a pragma that forces GCC into + * -O2, but the other one we can't control without "failed to inline always + * inline function due to target mismatch" warnings. + */ +#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ + && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ +# pragma GCC push_options +# pragma GCC optimize("-O2") +#endif + +#if XXH_VECTOR == XXH_NEON + +/* + * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 + * optimizes out the entire hashLong loop because of the aliasing violation. + * + * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, + * so the only option is to mark it as aliasing. + */ +typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; + +/*! + * @internal + * @brief `vld1q_u64` but faster and alignment-safe. + * + * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only + * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). + * + * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it + * prohibits load-store optimizations. Therefore, a direct dereference is used. + * + * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe + * unaligned load. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ +{ + return *(xxh_aliasing_uint64x2_t const *)ptr; +} +#else +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) +{ + return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); +} +#endif + +/*! + * @internal + * @brief `vmlal_u32` on low and high halves of a vector. + * + * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with + * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` + * with `vmlal_u32`. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* Inline assembly is the only way */ + __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); + return acc; +} +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* This intrinsic works as expected */ + return vmlal_high_u32(acc, lhs, rhs); +} +#else +/* Portable intrinsic versions */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); +} +/*! @copydoc XXH_vmlal_low_u32 + * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); +} +#endif + +/*! + * @ingroup tuning + * @brief Controls the NEON to scalar ratio for XXH3 + * + * This can be set to 2, 4, 6, or 8. + * + * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. + * + * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those + * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU + * bandwidth. + * + * This is even more noticeable on the more advanced cores like the Cortex-A76 which + * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. + * + * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes + * and 2 scalar lanes, which is chosen by default. + * + * This does not apply to Apple processors or 32-bit processors, which run better with + * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. + * + * This change benefits CPUs with large micro-op buffers without negatively affecting + * most other CPUs: + * + * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | + * |:----------------------|:--------------------|----------:|-----------:|------:| + * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | + * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | + * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | + * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | + * + * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. + * + * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning + * it effectively becomes worse 4. + * + * @see XXH3_accumulate_512_neon() + */ +# ifndef XXH3_NEON_LANES +# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ + && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 +# define XXH3_NEON_LANES 6 +# else +# define XXH3_NEON_LANES XXH_ACC_NB +# endif +# endif +#endif /* XXH_VECTOR == XXH_NEON */ + +/* + * VSX and Z Vector helpers. + * + * This is very messy, and any pull requests to clean this up are welcome. + * + * There are a lot of problems with supporting VSX and s390x, due to + * inconsistent intrinsics, spotty coverage, and multiple endiannesses. + */ +#if XXH_VECTOR == XXH_VSX +/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, + * and `pixel`. This is a problem for obvious reasons. + * + * These keywords are unnecessary; the spec literally says they are + * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd + * after including the header. + * + * We use pragma push_macro/pop_macro to keep the namespace clean. */ +# pragma push_macro("bool") +# pragma push_macro("vector") +# pragma push_macro("pixel") +/* silence potential macro redefined warnings */ +# undef bool +# undef vector +# undef pixel + +# if defined(__s390x__) +# include +# else +# include +# endif + +/* Restore the original macro values, if applicable. */ +# pragma pop_macro("pixel") +# pragma pop_macro("vector") +# pragma pop_macro("bool") + +typedef __vector unsigned long long xxh_u64x2; +typedef __vector unsigned char xxh_u8x16; +typedef __vector unsigned xxh_u32x4; + +/* + * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. + */ +typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; + +# ifndef XXH_VSX_BE +# if defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_VSX_BE 1 +# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ +# warning "-maltivec=be is not recommended. Please use native endianness." +# define XXH_VSX_BE 1 +# else +# define XXH_VSX_BE 0 +# endif +# endif /* !defined(XXH_VSX_BE) */ + +# if XXH_VSX_BE +# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) +# define XXH_vec_revb vec_revb +# else +/*! + * A polyfill for POWER9's vec_revb(). + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) +{ + xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + return vec_perm(val, val, vByteSwap); +} +# endif +# endif /* XXH_VSX_BE */ + +/*! + * Performs an unaligned vector load and byte swaps it on big endian. + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) +{ + xxh_u64x2 ret; + XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); +# if XXH_VSX_BE + ret = XXH_vec_revb(ret); +# endif + return ret; +} + +/* + * vec_mulo and vec_mule are very problematic intrinsics on PowerPC + * + * These intrinsics weren't added until GCC 8, despite existing for a while, + * and they are endian dependent. Also, their meaning swap depending on version. + * */ +# if defined(__s390x__) + /* s390x is always big endian, no issue on this platform */ +# define XXH_vec_mulo vec_mulo +# define XXH_vec_mule vec_mule +# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) +/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ + /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ +# define XXH_vec_mulo __builtin_altivec_vmulouw +# define XXH_vec_mule __builtin_altivec_vmuleuw +# else +/* gcc needs inline assembly */ +/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +# endif /* XXH_vec_mulo, XXH_vec_mule */ +#endif /* XXH_VECTOR == XXH_VSX */ + +#if XXH_VECTOR == XXH_SVE +#define ACCRND(acc, offset) \ +do { \ + svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ + svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ + svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ + svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ + svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ + svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ + svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ + acc = svadd_u64_x(mask, acc, mul); \ +} while (0) +#endif /* XXH_VECTOR == XXH_SVE */ + +/* prefetch + * can be disabled, by declaring XXH_NO_PREFETCH build macro */ +#if defined(XXH_NO_PREFETCH) +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +#else +# if XXH_SIZE_OPT >= 1 +# define XXH_PREFETCH(ptr) (void)(ptr) +# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ +# include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ +# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) +# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) +# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) +# else +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +# endif +#endif /* XXH_NO_PREFETCH */ + + +/* ========================================== + * XXH3 default settings + * ========================================== */ + +#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ + +#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) +# error "default keyset is not large enough" +#endif + +/*! Pseudorandom secret taken directly from FARSH. */ +XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { + 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, + 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, + 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, + 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, + 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, + 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, + 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, + 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, + 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, + 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, + 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, + 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, +}; + +static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ +static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ + +#ifdef XXH_OLD_NAMES +# define kSecret XXH3_kSecret +#endif + +#ifdef XXH_DOXYGEN +/*! + * @brief Calculates a 32-bit to 64-bit long multiply. + * + * Implemented as a macro. + * + * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't + * need to (but it shouldn't need to anyways, it is about 7 instructions to do + * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we + * use that instead of the normal method. + * + * If you are compiling for platforms like Thumb-1 and don't have a better option, + * you may also want to write your own long multiply routine here. + * + * @param x, y Numbers to be multiplied + * @return 64-bit product of the low 32 bits of @p x and @p y. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64(xxh_u64 x, xxh_u64 y) +{ + return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); +} +#elif defined(_MSC_VER) && defined(_M_IX86) +# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) +#else +/* + * Downcast + upcast is usually better than masking on older compilers like + * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. + * + * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands + * and perform a full 64x64 multiply -- entirely redundant on 32-bit. + */ +# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) +#endif + +/*! + * @brief Calculates a 64->128-bit long multiply. + * + * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar + * version. + * + * @param lhs , rhs The 64-bit integers to be multiplied + * @return The 128-bit result represented in an @ref XXH128_hash_t. + */ +static XXH128_hash_t +XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) +{ + /* + * GCC/Clang __uint128_t method. + * + * On most 64-bit targets, GCC and Clang define a __uint128_t type. + * This is usually the best way as it usually uses a native long 64-bit + * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. + * + * Usually. + * + * Despite being a 32-bit platform, Clang (and emscripten) define this type + * despite not having the arithmetic for it. This results in a laggy + * compiler builtin call which calculates a full 128-bit multiply. + * In that case it is best to use the portable one. + * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 + */ +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ + && defined(__SIZEOF_INT128__) \ + || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) + + __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; + XXH128_hash_t r128; + r128.low64 = (xxh_u64)(product); + r128.high64 = (xxh_u64)(product >> 64); + return r128; + + /* + * MSVC for x64's _umul128 method. + * + * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); + * + * This compiles to single operand MUL on x64. + */ +#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(_umul128) +#endif + xxh_u64 product_high; + xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); + XXH128_hash_t r128; + r128.low64 = product_low; + r128.high64 = product_high; + return r128; + + /* + * MSVC for ARM64's __umulh method. + * + * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. + */ +#elif defined(_M_ARM64) || defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(__umulh) +#endif + XXH128_hash_t r128; + r128.low64 = lhs * rhs; + r128.high64 = __umulh(lhs, rhs); + return r128; + +#else + /* + * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. + * + * This is a fast and simple grade school multiply, which is shown below + * with base 10 arithmetic instead of base 0x100000000. + * + * 9 3 // D2 lhs = 93 + * x 7 5 // D2 rhs = 75 + * ---------- + * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 + * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 + * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 + * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 + * --------- + * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 + * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 + * --------- + * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 + * + * The reasons for adding the products like this are: + * 1. It avoids manual carry tracking. Just like how + * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. + * This avoids a lot of complexity. + * + * 2. It hints for, and on Clang, compiles to, the powerful UMAAL + * instruction available in ARM's Digital Signal Processing extension + * in 32-bit ARMv6 and later, which is shown below: + * + * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) + * { + * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; + * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); + * *RdHi = (xxh_u32)(product >> 32); + * } + * + * This instruction was designed for efficient long multiplication, and + * allows this to be calculated in only 4 instructions at speeds + * comparable to some 64-bit ALUs. + * + * 3. It isn't terrible on other platforms. Usually this will be a couple + * of 32-bit ADD/ADCs. + */ + + /* First calculate all of the cross products. */ + xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); + xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); + xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); + xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); + + /* Now add the products together. These will never overflow. */ + xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; + xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; + xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); + + XXH128_hash_t r128; + r128.low64 = lower; + r128.high64 = upper; + return r128; +#endif +} + +/*! + * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. + * + * The reason for the separate function is to prevent passing too many structs + * around by value. This will hopefully inline the multiply, but we don't force it. + * + * @param lhs , rhs The 64-bit integers to multiply + * @return The low 64 bits of the product XOR'd by the high 64 bits. + * @see XXH_mult64to128() + */ +static xxh_u64 +XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) +{ + XXH128_hash_t product = XXH_mult64to128(lhs, rhs); + return product.low64 ^ product.high64; +} + +/*! Seems to produce slightly better code on GCC for some reason. */ +XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) +{ + XXH_ASSERT(0 <= shift && shift < 64); + return v64 ^ (v64 >> shift); +} + +/* + * This is a fast avalanche stage, + * suitable when input bits are already partially mixed + */ +static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) +{ + h64 = XXH_xorshift64(h64, 37); + h64 *= PRIME_MX1; + h64 = XXH_xorshift64(h64, 32); + return h64; +} + +/* + * This is a stronger avalanche, + * inspired by Pelle Evensen's rrmxmx + * preferable when input has not been previously mixed + */ +static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) +{ + /* this mix is inspired by Pelle Evensen's rrmxmx */ + h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); + h64 *= PRIME_MX2; + h64 ^= (h64 >> 35) + len ; + h64 *= PRIME_MX2; + return XXH_xorshift64(h64, 28); +} + + +/* ========================================== + * Short keys + * ========================================== + * One of the shortcomings of XXH32 and XXH64 was that their performance was + * sub-optimal on short lengths. It used an iterative algorithm which strongly + * favored lengths that were a multiple of 4 or 8. + * + * Instead of iterating over individual inputs, we use a set of single shot + * functions which piece together a range of lengths and operate in constant time. + * + * Additionally, the number of multiplies has been significantly reduced. This + * reduces latency, especially when emulating 64-bit multiplies on 32-bit. + * + * Depending on the platform, this may or may not be faster than XXH32, but it + * is almost guaranteed to be faster than XXH64. + */ + +/* + * At very short lengths, there isn't enough input to fully hide secrets, or use + * the entire secret. + * + * There is also only a limited amount of mixing we can do before significantly + * impacting performance. + * + * Therefore, we use different sections of the secret and always mix two secret + * samples with an XOR. This should have no effect on performance on the + * seedless or withSeed variants because everything _should_ be constant folded + * by modern compilers. + * + * The XOR mixing hides individual parts of the secret and increases entropy. + * + * This adds an extra layer of strength for custom secrets. + */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combined = { input[0], 0x01, input[0], input[0] } + * len = 2: combined = { input[1], 0x02, input[0], input[1] } + * len = 3: combined = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; + return XXH64_avalanche(keyed); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input1 = XXH_readLE32(input); + xxh_u32 const input2 = XXH_readLE32(input + len - 4); + xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; + xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); + xxh_u64 const keyed = input64 ^ bitflip; + return XXH3_rrmxmx(keyed, len); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; + xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; + xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; + xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; + xxh_u64 const acc = len + + XXH_swap64(input_lo) + input_hi + + XXH3_mul128_fold64(input_lo, input_hi); + return XXH3_avalanche(acc); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); + if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); + if (len) return XXH3_len_1to3_64b(input, len, secret, seed); + return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); + } +} + +/* + * DISCLAIMER: There are known *seed-dependent* multicollisions here due to + * multiplication by zero, affecting hashes of lengths 17 to 240. + * + * However, they are very unlikely. + * + * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all + * unseeded non-cryptographic hashes, it does not attempt to defend itself + * against specially crafted inputs, only random inputs. + * + * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes + * cancelling out the secret is taken an arbitrary number of times (addressed + * in XXH3_accumulate_512), this collision is very unlikely with random inputs + * and/or proper seeding: + * + * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a + * function that is only called up to 16 times per hash with up to 240 bytes of + * input. + * + * This is not too bad for a non-cryptographic hash function, especially with + * only 64 bit outputs. + * + * The 128-bit variant (which trades some speed for strength) is NOT affected + * by this, although it is always a good idea to use a proper seed if you care + * about strength. + */ +XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) +{ +#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ + /* + * UGLY HACK: + * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in + * slower code. + * + * By forcing seed64 into a register, we disrupt the cost model and + * cause it to scalarize. See `XXH32_round()` + * + * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, + * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on + * GCC 9.2, despite both emitting scalar code. + * + * GCC generates much better scalar code than Clang for the rest of XXH3, + * which is why finding a more optimal codepath is an interest. + */ + XXH_COMPILER_GUARD(seed64); +#endif + { xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 const input_hi = XXH_readLE64(input+8); + return XXH3_mul128_fold64( + input_lo ^ (XXH_readLE64(secret) + seed64), + input_hi ^ (XXH_readLE64(secret+8) - seed64) + ); + } +} + +/* For mid range keys, XXH3 uses a Mum-hash variant. */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { xxh_u64 acc = len * XXH_PRIME64_1; +#if XXH_SIZE_OPT >= 1 + /* Smaller and cleaner, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); + acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); + } while (i-- != 0); +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc += XXH3_mix16B(input+48, secret+96, seed); + acc += XXH3_mix16B(input+len-64, secret+112, seed); + } + acc += XXH3_mix16B(input+32, secret+64, seed); + acc += XXH3_mix16B(input+len-48, secret+80, seed); + } + acc += XXH3_mix16B(input+16, secret+32, seed); + acc += XXH3_mix16B(input+len-32, secret+48, seed); + } + acc += XXH3_mix16B(input+0, secret+0, seed); + acc += XXH3_mix16B(input+len-16, secret+16, seed); +#endif + return XXH3_avalanche(acc); + } +} + +/*! + * @brief Maximum size of "short" key in bytes. + */ +#define XXH3_MIDSIZE_MAX 240 + +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + #define XXH3_MIDSIZE_STARTOFFSET 3 + #define XXH3_MIDSIZE_LASTOFFSET 17 + + { xxh_u64 acc = len * XXH_PRIME64_1; + xxh_u64 acc_end; + unsigned int const nbRounds = (unsigned int)len / 16; + unsigned int i; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + for (i=0; i<8; i++) { + acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); + } + /* last bytes */ + acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); + XXH_ASSERT(nbRounds >= 8); + acc = XXH3_avalanche(acc); +#if defined(__clang__) /* Clang */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. + * In everywhere else, it uses scalar code. + * + * For 64->128-bit multiplies, even if the NEON was 100% optimal, it + * would still be slower than UMAAL (see XXH_mult64to128). + * + * Unfortunately, Clang doesn't handle the long multiplies properly and + * converts them to the nonexistent "vmulq_u64" intrinsic, which is then + * scalarized into an ugly mess of VMOV.32 instructions. + * + * This mess is difficult to avoid without turning autovectorization + * off completely, but they are usually relatively minor and/or not + * worth it to fix. + * + * This loop is the easiest to fix, as unlike XXH32, this pragma + * _actually works_ because it is a loop vectorization instead of an + * SLP vectorization. + */ + #pragma clang loop vectorize(disable) +#endif + for (i=8 ; i < nbRounds; i++) { + /* + * Prevents clang for unrolling the acc loop and interleaving with this one. + */ + XXH_COMPILER_GUARD(acc); + acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); + } + return XXH3_avalanche(acc + acc_end); + } +} + + +/* ======= Long Keys ======= */ + +#define XXH_STRIPE_LEN 64 +#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ +#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) + +#ifdef XXH_OLD_NAMES +# define STRIPE_LEN XXH_STRIPE_LEN +# define ACC_NB XXH_ACC_NB +#endif + +#ifndef XXH_PREFETCH_DIST +# ifdef __clang__ +# define XXH_PREFETCH_DIST 320 +# else +# if (XXH_VECTOR == XXH_AVX512) +# define XXH_PREFETCH_DIST 512 +# else +# define XXH_PREFETCH_DIST 384 +# endif +# endif /* __clang__ */ +#endif /* XXH_PREFETCH_DIST */ + +/* + * These macros are to generate an XXH3_accumulate() function. + * The two arguments select the name suffix and target attribute. + * + * The name of this symbol is XXH3_accumulate_() and it calls + * XXH3_accumulate_512_(). + * + * It may be useful to hand implement this function if the compiler fails to + * optimize the inline function. + */ +#define XXH3_ACCUMULATE_TEMPLATE(name) \ +void \ +XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ + const xxh_u8* XXH_RESTRICT input, \ + const xxh_u8* XXH_RESTRICT secret, \ + size_t nbStripes) \ +{ \ + size_t n; \ + for (n = 0; n < nbStripes; n++ ) { \ + const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ + XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ + XXH3_accumulate_512_##name( \ + acc, \ + in, \ + secret + n*XXH_SECRET_CONSUME_RATE); \ + } \ +} + + +XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) +{ + if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); + XXH_memcpy(dst, &v64, sizeof(v64)); +} + +/* Several intrinsic functions below are supposed to accept __int64 as argument, + * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . + * However, several environments do not define __int64 type, + * requiring a workaround. + */ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) + typedef int64_t xxh_i64; +#else + /* the following type must have a width of 64-bit */ + typedef long long xxh_i64; +#endif + + +/* + * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. + * + * It is a hardened version of UMAC, based off of FARSH's implementation. + * + * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD + * implementations, and it is ridiculously fast. + * + * We harden it by mixing the original input to the accumulators as well as the product. + * + * This means that in the (relatively likely) case of a multiply by zero, the + * original input is preserved. + * + * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve + * cross-pollination, as otherwise the upper and lower halves would be + * essentially independent. + * + * This doesn't matter on 64-bit hashes since they all get merged together in + * the end, so we skip the extra step. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +#if (XXH_VECTOR == XXH_AVX512) \ + || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) + +#ifndef XXH_TARGET_AVX512 +# define XXH_TARGET_AVX512 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + __m512i* const xacc = (__m512i *) acc; + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + + { + /* data_vec = input[0]; */ + __m512i const data_vec = _mm512_loadu_si512 (input); + /* key_vec = secret[0]; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + /* data_key = data_vec ^ key_vec; */ + __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); + /* xacc[0] += swap(data_vec); */ + __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); + __m512i const sum = _mm512_add_epi64(*xacc, data_swap); + /* xacc[0] += product; */ + *xacc = _mm512_add_epi64(product, sum); + } +} +XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) + +/* + * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. + * + * Multiplication isn't perfect, as explained by Google in HighwayHash: + * + * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to + * // varying degrees. In descending order of goodness, bytes + * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. + * // As expected, the upper and lower bytes are much worse. + * + * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 + * + * Since our algorithm uses a pseudorandom secret to add some variance into the + * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. + * + * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid + * extraction. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + { __m512i* const xacc = (__m512i*) acc; + const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); + + /* xacc[0] ^= (xacc[0] >> 47) */ + __m512i const acc_vec = *xacc; + __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); + /* xacc[0] ^= secret; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); + + /* xacc[0] *= XXH_PRIME32_1; */ + __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); + __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); + __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); + *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); + XXH_ASSERT(((size_t)customSecret & 63) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); + __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); + __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); + + const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); + __m512i* const dest = ( __m512i*) customSecret; + int i; + XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 63) == 0); + for (i=0; i < nbRounds; ++i) { + dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_AVX2) \ + || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) + +#ifndef XXH_TARGET_AVX2 +# define XXH_TARGET_AVX2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xinput = (const __m256i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* data_vec = xinput[i]; */ + __m256i const data_vec = _mm256_loadu_si256 (xinput+i); + /* key_vec = xsecret[i]; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); + __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm256_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m256i const acc_vec = xacc[i]; + __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); + __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); + /* xacc[i] ^= xsecret; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); + __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); + __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); + (void)(&XXH_writeLE64); + XXH_PREFETCH(customSecret); + { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); + + const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); + __m256i* dest = ( __m256i*) customSecret; + +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dest); +# endif + XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 31) == 0); + + /* GCC -O2 need unroll loop manually */ + dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); + dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); + dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); + dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); + dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); + dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); + } +} + +#endif + +/* x86dispatch always generates SSE2 */ +#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) + +#ifndef XXH_TARGET_SSE2 +# define XXH_TARGET_SSE2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* SSE2 is just a half-scale version of the AVX2 version. */ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xinput = (const __m128i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = _mm_loadu_si128 (xinput+i); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); + __m128i const sum = _mm_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); + __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); + __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); + +# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 + /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ + XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; + __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); +# else + __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); +# endif + int i; + + const void* const src16 = XXH3_kSecret; + __m128i* dst16 = (__m128i*) customSecret; +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dst16); +# endif + XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dst16 & 15) == 0); + + for (i=0; i < nbRounds; ++i) { + dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_NEON) + +/* forward declarations for the scalar routines */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, size_t lane); + +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, size_t lane); + +/*! + * @internal + * @brief The bulk processing loop for NEON and WASM SIMD128. + * + * The NEON code path is actually partially scalar when running on AArch64. This + * is to optimize the pipelining and can have up to 15% speedup depending on the + * CPU, and it also mitigates some GCC codegen issues. + * + * @see XXH3_NEON_LANES for configuring this and details about this optimization. + * + * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit + * integers instead of the other platforms which mask full 64-bit vectors, + * so the setup is more complicated than just shifting right. + * + * Additionally, there is an optimization for 4 lanes at once noted below. + * + * Since, as stated, the most optimal amount of lanes for Cortexes is 6, + * there needs to be *three* versions of the accumulate operation used + * for the remaining 2 lanes. + * + * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap + * nearly perfectly. + */ + +XXH_FORCE_INLINE void +XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); + { /* GCC for darwin arm64 does not like aliasing here */ + xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; + /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ + uint8_t const* xinput = (const uint8_t *) input; + uint8_t const* xsecret = (const uint8_t *) secret; + + size_t i; +#ifdef __wasm_simd128__ + /* + * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret + * is constant propagated, which results in it converting it to this + * inside the loop: + * + * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) + * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) + * ... + * + * This requires a full 32-bit address immediate (and therefore a 6 byte + * instruction) as well as an add for each offset. + * + * Putting an asm guard prevents it from folding (at the cost of losing + * the alignment hint), and uses the free offset in `v128.load` instead + * of adding secret_offset each time which overall reduces code size by + * about a kilobyte and improves performance. + */ + XXH_COMPILER_GUARD(xsecret); +#endif + /* Scalar lanes use the normal scalarRound routine */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } + i = 0; + /* 4 NEON lanes at a time. */ + for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); + uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); + /* data_swap = swap(data_vec) */ + uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); + uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); + uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); + + /* + * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a + * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to + * get one vector with the low 32 bits of each lane, and one vector + * with the high 32 bits of each lane. + * + * The intrinsic returns a double vector because the original ARMv7-a + * instruction modified both arguments in place. AArch64 and SIMD128 emit + * two instructions from this intrinsic. + * + * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] + * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] + */ + uint32x4x2_t unzipped = vuzpq_u32( + vreinterpretq_u32_u64(data_key_1), + vreinterpretq_u32_u64(data_key_2) + ); + /* data_key_lo = data_key & 0xFFFFFFFF */ + uint32x4_t data_key_lo = unzipped.val[0]; + /* data_key_hi = data_key >> 32 */ + uint32x4_t data_key_hi = unzipped.val[1]; + /* + * Then, we can split the vectors horizontally and multiply which, as for most + * widening intrinsics, have a variant that works on both high half vectors + * for free on AArch64. A similar instruction is available on SIMD128. + * + * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi + */ + uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); + uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); + /* + * Clang reorders + * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s + * c += a; // add acc.2d, acc.2d, swap.2d + * to + * c += a; // add acc.2d, acc.2d, swap.2d + * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s + * + * While it would make sense in theory since the addition is faster, + * for reasons likely related to umlal being limited to certain NEON + * pipelines, this is worse. A compiler guard fixes this. + */ + XXH_COMPILER_GUARD_CLANG_NEON(sum_1); + XXH_COMPILER_GUARD_CLANG_NEON(sum_2); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64(xacc[i], sum_1); + xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); + } + /* Operate on the remaining NEON lanes 2 at a time. */ + for (; i < XXH3_NEON_LANES / 2; i++) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + /* acc_vec_2 = swap(data_vec) */ + uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* For two lanes, just use VMOVN and VSHRN. */ + /* data_key_lo = data_key & 0xFFFFFFFF; */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* data_key_hi = data_key >> 32; */ + uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); + /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ + uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); + /* Same Clang workaround as before */ + XXH_COMPILER_GUARD_CLANG_NEON(sum); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64 (xacc[i], sum); + } + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; + uint8_t const* xsecret = (uint8_t const*) secret; + + size_t i; + /* WASM uses operator overloads and doesn't need these. */ +#ifndef __wasm_simd128__ + /* { prime32_1, prime32_1 } */ + uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); + /* { 0, prime32_1, 0, prime32_1 } */ + uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); +#endif + + /* AArch64 uses both scalar and neon at the same time */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } + for (i=0; i < XXH3_NEON_LANES / 2; i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + uint64x2_t acc_vec = xacc[i]; + uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); + uint64x2_t data_vec = veorq_u64(acc_vec, shifted); + + /* xacc[i] ^= xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* xacc[i] *= XXH_PRIME32_1 */ +#ifdef __wasm_simd128__ + /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ + xacc[i] = data_key * XXH_PRIME32_1; +#else + /* + * Expanded version with portable NEON intrinsics + * + * lo(x) * lo(y) + (hi(x) * lo(y) << 32) + * + * prod_hi = hi(data_key) * lo(prime) << 32 + * + * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector + * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits + * and avoid the shift. + */ + uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); + /* Extract low bits for vmlal_u32 */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ + xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); +#endif + } + } +} +#endif + +#if (XXH_VECTOR == XXH_VSX) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* presumed aligned */ + xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ + xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ + xxh_u64x2 const v32 = { 32, 32 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* data_vec = xinput[i]; */ + xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); + /* key_vec = xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + /* shuffled = (data_key << 32) | (data_key >> 32); */ + xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); + /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ + xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); + /* acc_vec = xacc[i]; */ + xxh_u64x2 acc_vec = xacc[i]; + acc_vec += product; + + /* swap high and low halves */ +#ifdef __s390x__ + acc_vec += vec_permi(data_vec, data_vec, 2); +#else + acc_vec += vec_xxpermdi(data_vec, data_vec, 2); +#endif + xacc[i] = acc_vec; + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + const xxh_u8* const xsecret = (const xxh_u8*) secret; + /* constants */ + xxh_u64x2 const v32 = { 32, 32 }; + xxh_u64x2 const v47 = { 47, 47 }; + xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + xxh_u64x2 const acc_vec = xacc[i]; + xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); + + /* xacc[i] ^= xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + + /* xacc[i] *= XXH_PRIME32_1 */ + /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ + xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); + /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ + xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); + xacc[i] = prod_odd + (prod_even << v32); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_SVE) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc); + ACCRND(vacc, 0); + svst1_u64(mask, xacc, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } +} + +XXH_FORCE_INLINE void +XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, + size_t nbStripes) +{ + if (nbStripes != 0) { + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc + 0); + do { + /* svprfd(svbool_t, void *, enum svfprop); */ + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(vacc, 0); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } + } +} + +#endif + +/* scalar variants - universal */ + +#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) +/* + * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they + * emit an excess mask and a full 64-bit multiply-add (MADD X-form). + * + * While this might not seem like much, as AArch64 is a 64-bit architecture, only + * big Cortex designs have a full 64-bit multiplier. + * + * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit + * multiplies expand to 2-3 multiplies in microcode. This has a major penalty + * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. + * + * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does + * not have this penalty and does the mask automatically. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + xxh_u64 ret; + /* note: %x = 64-bit register, %w = 32-bit register */ + __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); + return ret; +} +#else +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; +} +#endif + +/*! + * @internal + * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* xacc = (xxh_u64*) acc; + xxh_u8 const* xinput = (xxh_u8 const*) input; + xxh_u8 const* xsecret = (xxh_u8 const*) secret; + XXH_ASSERT(lane < XXH_ACC_NB); + XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + { + xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); + xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); + xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ + xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); + } +} + +/*! + * @internal + * @brief Processes a 64 byte block of data using the scalar path. + */ +XXH_FORCE_INLINE void +XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + size_t i; + /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ +#if defined(__GNUC__) && !defined(__clang__) \ + && (defined(__arm__) || defined(__thumb2__)) \ + && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ + && XXH_SIZE_OPT <= 0 +# pragma GCC unroll 8 +#endif + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) + +/*! + * @internal + * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ + XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); + XXH_ASSERT(lane < XXH_ACC_NB); + { + xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); + xxh_u64 acc64 = xacc[lane]; + acc64 = XXH_xorshift64(acc64, 47); + acc64 ^= key64; + acc64 *= XXH_PRIME32_1; + xacc[lane] = acc64; + } +} + +/*! + * @internal + * @brief Scrambles the accumulators after a large chunk has been read + */ +XXH_FORCE_INLINE void +XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + size_t i; + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } +} + +XXH_FORCE_INLINE void +XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + /* + * We need a separate pointer for the hack below, + * which requires a non-const pointer. + * Any decent compiler will optimize this out otherwise. + */ + const xxh_u8* kSecretPtr = XXH3_kSecret; + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + +#if defined(__GNUC__) && defined(__aarch64__) + /* + * UGLY HACK: + * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are + * placed sequentially, in order, at the top of the unrolled loop. + * + * While MOVK is great for generating constants (2 cycles for a 64-bit + * constant compared to 4 cycles for LDR), it fights for bandwidth with + * the arithmetic instructions. + * + * I L S + * MOVK + * MOVK + * MOVK + * MOVK + * ADD + * SUB STR + * STR + * By forcing loads from memory (as the asm line causes the compiler to assume + * that XXH3_kSecretPtr has been changed), the pipelines are used more + * efficiently: + * I L S + * LDR + * ADD LDR + * SUB STR + * STR + * + * See XXH3_NEON_LANES for details on the pipsline. + * + * XXH3_64bits_withSeed, len == 256, Snapdragon 835 + * without hack: 2654.4 MB/s + * with hack: 3202.9 MB/s + */ + XXH_COMPILER_GUARD(kSecretPtr); +#endif + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; + int i; + for (i=0; i < nbRounds; i++) { + /* + * The asm hack causes the compiler to assume that kSecretPtr aliases with + * customSecret, and on aarch64, this prevented LDP from merging two + * loads together for free. Putting the loads together before the stores + * properly generates LDP. + */ + xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; + xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; + XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); + XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); + } } +} + + +typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); +typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); +typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); + + +#if (XXH_VECTOR == XXH_AVX512) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx512 +#define XXH3_accumulate XXH3_accumulate_avx512 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 + +#elif (XXH_VECTOR == XXH_AVX2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx2 +#define XXH3_accumulate XXH3_accumulate_avx2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 + +#elif (XXH_VECTOR == XXH_SSE2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_sse2 +#define XXH3_accumulate XXH3_accumulate_sse2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 + +#elif (XXH_VECTOR == XXH_NEON) + +#define XXH3_accumulate_512 XXH3_accumulate_512_neon +#define XXH3_accumulate XXH3_accumulate_neon +#define XXH3_scrambleAcc XXH3_scrambleAcc_neon +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_VSX) + +#define XXH3_accumulate_512 XXH3_accumulate_512_vsx +#define XXH3_accumulate XXH3_accumulate_vsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_SVE) +#define XXH3_accumulate_512 XXH3_accumulate_512_sve +#define XXH3_accumulate XXH3_accumulate_sve +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#else /* scalar */ + +#define XXH3_accumulate_512 XXH3_accumulate_512_scalar +#define XXH3_accumulate XXH3_accumulate_scalar +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#endif + +#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ +# undef XXH3_initCustomSecret +# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#endif + +XXH_FORCE_INLINE void +XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; + size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; + size_t const nb_blocks = (len - 1) / block_len; + + size_t n; + + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + + for (n = 0; n < nb_blocks; n++) { + f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); + f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); + } + + /* last partial block */ + XXH_ASSERT(len > XXH_STRIPE_LEN); + { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; + XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); + f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); + + /* last stripe */ + { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; +#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ + XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); + } } +} + +XXH_FORCE_INLINE xxh_u64 +XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) +{ + return XXH3_mul128_fold64( + acc[0] ^ XXH_readLE64(secret), + acc[1] ^ XXH_readLE64(secret+8) ); +} + +static XXH64_hash_t +XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) +{ + xxh_u64 result64 = start; + size_t i = 0; + + for (i = 0; i < 4; i++) { + result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); +#if defined(__clang__) /* Clang */ \ + && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Prevent autovectorization on Clang ARMv7-a. Exact same problem as + * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. + * XXH3_64bits, len == 256, Snapdragon 835: + * without hack: 2063.7 MB/s + * with hack: 2560.7 MB/s + */ + XXH_COMPILER_GUARD(result64); +#endif + } + + return XXH3_avalanche(result64); +} + +#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ + XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, + const void* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + /* do not align on 8, so that the secret is different from the accumulator */ +#define XXH_SECRET_MERGEACCS_START 11 + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); +} + +/* + * It's important for performance to transmit secret's size (when it's static) + * so that the compiler can properly optimize the vectorized loop. + * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's preferable for performance that XXH3_hashLong is not inlined, + * as it results in a smaller function for small data, easier to the instruction cache. + * Note that inside this no_inline function, we do inline the internal loop, + * and provide a statically defined secret size to allow optimization of vector loop. + */ +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * XXH3_hashLong_64b_withSeed(): + * Generate a custom key based on alteration of default XXH3_kSecret with the seed, + * and then use this key for long mode hashing. + * + * This operation is decently fast but nonetheless costs a little bit of time. + * Try to avoid it whenever possible (typically when seed==0). + * + * It's important for performance that XXH3_hashLong is not inlined. Not sure + * why (uop cache maybe?), but the difference is large and easily measurable. + */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, + XXH64_hash_t seed, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ +#if XXH_SIZE_OPT <= 0 + if (seed == 0) + return XXH3_hashLong_64b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); +#endif + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed); + return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_64b_withSeed_internal(input, len, seed, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + + +typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong64_f f_hashLong) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secretLen` condition is not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + * Also, note that function signature doesn't offer room to return an error. + */ + if (len <= 16) + return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); +} + + +/* === Public entry point === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) +{ + return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); +} + +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (length <= XXH3_MIDSIZE_MAX) + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); +} + + +/* === XXH3 streaming === */ +#ifndef XXH_NO_STREAM +/* + * Malloc's a pointer that is always aligned to align. + * + * This must be freed with `XXH_alignedFree()`. + * + * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte + * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 + * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. + * + * This underalignment previously caused a rather obvious crash which went + * completely unnoticed due to XXH3_createState() not actually being tested. + * Credit to RedSpah for noticing this bug. + * + * The alignment is done manually: Functions like posix_memalign or _mm_malloc + * are avoided: To maintain portability, we would have to write a fallback + * like this anyways, and besides, testing for the existence of library + * functions without relying on external build tools is impossible. + * + * The method is simple: Overallocate, manually align, and store the offset + * to the original behind the returned pointer. + * + * Align must be a power of 2 and 8 <= align <= 128. + */ +static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) +{ + XXH_ASSERT(align <= 128 && align >= 8); /* range check */ + XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ + XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ + { /* Overallocate to make room for manual realignment and an offset byte */ + xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); + if (base != NULL) { + /* + * Get the offset needed to align this pointer. + * + * Even if the returned pointer is aligned, there will always be + * at least one byte to store the offset to the original pointer. + */ + size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ + /* Add the offset for the now-aligned pointer */ + xxh_u8* ptr = base + offset; + + XXH_ASSERT((size_t)ptr % align == 0); + + /* Store the offset immediately before the returned pointer. */ + ptr[-1] = (xxh_u8)offset; + return ptr; + } + return NULL; + } +} +/* + * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass + * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. + */ +static void XXH_alignedFree(void* p) +{ + if (p != NULL) { + xxh_u8* ptr = (xxh_u8*)p; + /* Get the offset byte we added in XXH_malloc. */ + xxh_u8 offset = ptr[-1]; + /* Free the original malloc'd pointer */ + xxh_u8* base = ptr - offset; + XXH_free(base); + } +} +/*! @ingroup XXH3_family */ +/*! + * @brief Allocate an @ref XXH3_state_t. + * + * @return An allocated pointer of @ref XXH3_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH3_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) +{ + XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); + if (state==NULL) return NULL; + XXH3_INITSTATE(state); + return state; +} + +/*! @ingroup XXH3_family */ +/*! + * @brief Frees an @ref XXH3_state_t. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * + * @return @ref XXH_OK. + * + * @note Must be allocated with XXH3_createState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) +{ + XXH_alignedFree(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) +{ + XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); +} + +static void +XXH3_reset_internal(XXH3_state_t* statePtr, + XXH64_hash_t seed, + const void* secret, size_t secretSize) +{ + size_t const initStart = offsetof(XXH3_state_t, bufferedSize); + size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; + XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); + XXH_ASSERT(statePtr != NULL); + /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ + memset((char*)statePtr + initStart, 0, initLength); + statePtr->acc[0] = XXH_PRIME32_3; + statePtr->acc[1] = XXH_PRIME64_1; + statePtr->acc[2] = XXH_PRIME64_2; + statePtr->acc[3] = XXH_PRIME64_3; + statePtr->acc[4] = XXH_PRIME64_4; + statePtr->acc[5] = XXH_PRIME32_2; + statePtr->acc[6] = XXH_PRIME64_5; + statePtr->acc[7] = XXH_PRIME32_1; + statePtr->seed = seed; + statePtr->useSeed = (seed != 0); + statePtr->extSecret = (const unsigned char*)secret; + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; + statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, secret, secretSize); + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + if (statePtr == NULL) return XXH_ERROR; + if (seed==0) return XXH3_64bits_reset(statePtr); + if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) + XXH3_initCustomSecret(statePtr->customSecret, seed); + XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) +{ + if (statePtr == NULL) return XXH_ERROR; + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + XXH3_reset_internal(statePtr, seed64, secret, secretSize); + statePtr->useSeed = 1; /* always, even if seed64==0 */ + return XXH_OK; +} + +/*! + * @internal + * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). + * + * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. + * + * @param acc Pointer to the 8 accumulator lanes + * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* + * @param nbStripesPerBlock Number of stripes in a block + * @param input Input pointer + * @param nbStripes Number of stripes to process + * @param secret Secret pointer + * @param secretLimit Offset of the last block in @p secret + * @param f_acc Pointer to an XXH3_accumulate implementation + * @param f_scramble Pointer to an XXH3_scrambleAcc implementation + * @return Pointer past the end of @p input after processing + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, + size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, + const xxh_u8* XXH_RESTRICT input, size_t nbStripes, + const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; + /* Process full blocks */ + if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { + /* Process the initial partial block... */ + size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; + + do { + /* Accumulate and scramble */ + f_acc(acc, input, initialSecret, nbStripesThisIter); + f_scramble(acc, secret + secretLimit); + input += nbStripesThisIter * XXH_STRIPE_LEN; + nbStripes -= nbStripesThisIter; + /* Then continue the loop with the full block size */ + nbStripesThisIter = nbStripesPerBlock; + initialSecret = secret; + } while (nbStripes >= nbStripesPerBlock); + *nbStripesSoFarPtr = 0; + } + /* Process a partial block */ + if (nbStripes > 0) { + f_acc(acc, input, initialSecret, nbStripes); + input += nbStripes * XXH_STRIPE_LEN; + *nbStripesSoFarPtr += nbStripes; + } + /* Return end pointer */ + return input; +} + +#ifndef XXH3_STREAM_USE_STACK +# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ +# define XXH3_STREAM_USE_STACK 1 +# endif +#endif +/* + * Both XXH3_64bits_update and XXH3_128bits_update use this routine. + */ +XXH_FORCE_INLINE XXH_errorcode +XXH3_update(XXH3_state_t* XXH_RESTRICT const state, + const xxh_u8* XXH_RESTRICT input, size_t len, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + XXH_ASSERT(state != NULL); + { const xxh_u8* const bEnd = input + len; + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* For some reason, gcc and MSVC seem to suffer greatly + * when operating accumulators directly into state. + * Operating into stack space seems to enable proper optimization. + * clang, on the other hand, doesn't seem to need this trick */ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; + XXH_memcpy(acc, state->acc, sizeof(acc)); +#else + xxh_u64* XXH_RESTRICT const acc = state->acc; +#endif + state->totalLen += len; + XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); + + /* small input : just fill in tmp buffer */ + if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + + /* total input is now > XXH3_INTERNALBUFFER_SIZE */ + #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) + XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ + + /* + * Internal buffer is partially filled (always, except at beginning) + * Complete it, then consume it. + */ + if (state->bufferedSize) { + size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; + XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); + input += loadSize; + XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, XXH3_INTERNALBUFFER_STRIPES, + secret, state->secretLimit, + f_acc, f_scramble); + state->bufferedSize = 0; + } + XXH_ASSERT(input < bEnd); + if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { + size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; + input = XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + input, nbStripes, + secret, state->secretLimit, + f_acc, f_scramble); + XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); + + } + /* Some remaining input (always) : buffer it */ + XXH_ASSERT(input < bEnd); + XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); + XXH_ASSERT(state->bufferedSize == 0); + XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); + state->bufferedSize = (XXH32_hash_t)(bEnd-input); +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* save stack accumulators into state */ + XXH_memcpy(state->acc, acc, sizeof(acc)); +#endif + } + + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_update(state, (const xxh_u8*)input, len, + XXH3_accumulate, XXH3_scrambleAcc); +} + + +XXH_FORCE_INLINE void +XXH3_digest_long (XXH64_hash_t* acc, + const XXH3_state_t* state, + const unsigned char* secret) +{ + xxh_u8 lastStripe[XXH_STRIPE_LEN]; + const xxh_u8* lastStripePtr; + + /* + * Digest on a local copy. This way, the state remains unaltered, and it can + * continue ingesting more input afterwards. + */ + XXH_memcpy(acc, state->acc, sizeof(state->acc)); + if (state->bufferedSize >= XXH_STRIPE_LEN) { + /* Consume remaining stripes then point to remaining data in buffer */ + size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; + size_t nbStripesSoFar = state->nbStripesSoFar; + XXH3_consumeStripes(acc, + &nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, nbStripes, + secret, state->secretLimit, + XXH3_accumulate, XXH3_scrambleAcc); + lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; + } else { /* bufferedSize < XXH_STRIPE_LEN */ + /* Copy to temp buffer */ + size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; + XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ + XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); + XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); + lastStripePtr = lastStripe; + } + /* Last stripe */ + XXH3_accumulate_512(acc, + lastStripePtr, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + return XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + } + /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ + if (state->useSeed) + return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ + + +/* ========================================== + * XXH3 128 bits (a.k.a XXH128) + * ========================================== + * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, + * even without counting the significantly larger output size. + * + * For example, extra steps are taken to avoid the seed-dependent collisions + * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). + * + * This strength naturally comes at the cost of some speed, especially on short + * lengths. Note that longer hashes are about as fast as the 64-bit version + * due to it using only a slight modification of the 64-bit loop. + * + * XXH128 is also more oriented towards 64-bit machines. It is still extremely + * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). + */ + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + /* A doubled version of 1to3_64b with different constants. */ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } + * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } + * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); + xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; + xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; + xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; + XXH128_hash_t h128; + h128.low64 = XXH64_avalanche(keyed_lo); + h128.high64 = XXH64_avalanche(keyed_hi); + return h128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input_lo = XXH_readLE32(input); + xxh_u32 const input_hi = XXH_readLE32(input + len - 4); + xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); + xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; + xxh_u64 const keyed = input_64 ^ bitflip; + + /* Shift len to the left to ensure it is even, this avoids even multiplies. */ + XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); + + m128.high64 += (m128.low64 << 1); + m128.low64 ^= (m128.high64 >> 3); + + m128.low64 = XXH_xorshift64(m128.low64, 35); + m128.low64 *= PRIME_MX2; + m128.low64 = XXH_xorshift64(m128.low64, 28); + m128.high64 = XXH3_avalanche(m128.high64); + return m128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; + xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; + xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 input_hi = XXH_readLE64(input + len - 8); + XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); + /* + * Put len in the middle of m128 to ensure that the length gets mixed to + * both the low and high bits in the 128x64 multiply below. + */ + m128.low64 += (xxh_u64)(len - 1) << 54; + input_hi ^= bitfliph; + /* + * Add the high 32 bits of input_hi to the high 32 bits of m128, then + * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to + * the high 64 bits of m128. + * + * The best approach to this operation is different on 32-bit and 64-bit. + */ + if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ + /* + * 32-bit optimized version, which is more readable. + * + * On 32-bit, it removes an ADC and delays a dependency between the two + * halves of m128.high64, but it generates an extra mask on 64-bit. + */ + m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); + } else { + /* + * 64-bit optimized (albeit more confusing) version. + * + * Uses some properties of addition and multiplication to remove the mask: + * + * Let: + * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) + * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) + * c = XXH_PRIME32_2 + * + * a + (b * c) + * Inverse Property: x + y - x == y + * a + (b * (1 + c - 1)) + * Distributive Property: x * (y + z) == (x * y) + (x * z) + * a + (b * 1) + (b * (c - 1)) + * Identity Property: x * 1 == x + * a + b + (b * (c - 1)) + * + * Substitute a, b, and c: + * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + * + * Since input_hi.hi + input_hi.lo == input_hi, we get this: + * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + */ + m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); + } + /* m128 ^= XXH_swap64(m128 >> 64); */ + m128.low64 ^= XXH_swap64(m128.high64); + + { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ + XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); + h128.high64 += m128.high64 * XXH_PRIME64_2; + + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = XXH3_avalanche(h128.high64); + return h128; + } } +} + +/* + * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN + */ +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); + if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); + if (len) return XXH3_len_1to3_128b(input, len, secret, seed); + { XXH128_hash_t h128; + xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); + xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); + h128.low64 = XXH64_avalanche(seed ^ bitflipl); + h128.high64 = XXH64_avalanche( seed ^ bitfliph); + return h128; + } } +} + +/* + * A bit slower than XXH3_mix16B, but handles multiply by zero better. + */ +XXH_FORCE_INLINE XXH128_hash_t +XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, + const xxh_u8* secret, XXH64_hash_t seed) +{ + acc.low64 += XXH3_mix16B (input_1, secret+0, seed); + acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); + acc.high64 += XXH3_mix16B (input_2, secret+16, seed); + acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); + return acc; +} + + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { XXH128_hash_t acc; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + +#if XXH_SIZE_OPT >= 1 + { + /* Smaller, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); + } while (i-- != 0); + } +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); + } + acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); + } + acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); + } + acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); +#endif + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + { XXH128_hash_t acc; + unsigned i; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + /* + * We set as `i` as offset + 32. We do this so that unchanged + * `len` can be used as upper bound. This reaches a sweet spot + * where both x86 and aarch64 get simple agen and good codegen + * for the loop. + */ + for (i = 32; i < 160; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + i - 32, + seed); + } + acc.low64 = XXH3_avalanche(acc.low64); + acc.high64 = XXH3_avalanche(acc.high64); + /* + * NB: `i <= len` will duplicate the last 32-bytes if + * len % 32 was zero. This is an unfortunate necessity to keep + * the hash result stable. + */ + for (i=160; i <= len; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, + seed); + } + /* last bytes */ + acc = XXH128_mix32B(acc, + input + len - 16, + input + len - 32, + secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, + (XXH64_hash_t)0 - seed); + + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)len * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + secretSize + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)len * XXH_PRIME64_2)); + return h128; + } +} + +/* + * It's important for performance that XXH3_hashLong() is not inlined. + */ +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's important for performance to pass @p secretLen (when it's static) + * to the compiler, so that it can properly optimize the vectorized loop. + * + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, + XXH3_accumulate, XXH3_scrambleAcc); +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ + if (seed64 == 0) + return XXH3_hashLong_128b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed64); + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + +typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const void* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_128bits_internal(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong128_f f_hl128) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secret` conditions are not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + */ + if (len <= 16) + return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hl128(input, len, seed64, secret, secretLen); +} + + +/* === Public XXH128 API === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_128bits_internal(input, len, 0, + (const xxh_u8*)secret, secretSize, + XXH3_hashLong_128b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_withSeed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_withSeed(input, len, seed); +} + + +/* === XXH3 128-bit streaming === */ +#ifndef XXH_NO_STREAM +/* + * All initialization and update functions are identical to 64-bit streaming variant. + * The only difference is the finalization routine. + */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + return XXH3_64bits_reset(statePtr); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSeed(statePtr, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_64bits_update(state, input, len); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + state->secretLimit + XXH_STRIPE_LEN + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); + return h128; + } + } + /* len <= XXH3_MIDSIZE_MAX : short code */ + if (state->seed) + return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ +/* 128-bit utility functions */ + +#include /* memcmp, memcpy */ + +/* return : 1 is equal, 0 if different */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) +{ + /* note : XXH128_hash_t is compact, it has no padding byte */ + return !(memcmp(&h1, &h2, sizeof(h1))); +} + +/* This prototype is compatible with stdlib's qsort(). + * @return : >0 if *h128_1 > *h128_2 + * <0 if *h128_1 < *h128_2 + * =0 if *h128_1 == *h128_2 */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) +{ + XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; + XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; + int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); + /* note : bets that, in most cases, hash values are different */ + if (hcmp) return hcmp; + return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); +} + + +/*====== Canonical representation ======*/ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) { + hash.high64 = XXH_swap64(hash.high64); + hash.low64 = XXH_swap64(hash.low64); + } + XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); + XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) +{ + XXH128_hash_t h; + h.high64 = XXH_readBE64(src); + h.low64 = XXH_readBE64(src->digest + 8); + return h; +} + + + +/* ========================================== + * Secret generators + * ========================================== + */ +#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) + +XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) +{ + XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); + XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) +{ +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(secretBuffer != NULL); + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); +#else + /* production mode, assert() are disabled */ + if (secretBuffer == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; +#endif + + if (customSeedSize == 0) { + customSeed = XXH3_kSecret; + customSeedSize = XXH_SECRET_DEFAULT_SIZE; + } +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(customSeed != NULL); +#else + if (customSeed == NULL) return XXH_ERROR; +#endif + + /* Fill secretBuffer with a copy of customSeed - repeat as needed */ + { size_t pos = 0; + while (pos < secretSize) { + size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); + memcpy((char*)secretBuffer + pos, customSeed, toCopy); + pos += toCopy; + } } + + { size_t const nbSeg16 = secretSize / 16; + size_t n; + XXH128_canonical_t scrambler; + XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); + for (n=0; n Date: Tue, 6 Feb 2024 16:45:45 +0100 Subject: [PATCH 51/60] FIX: `checksum` with `file!` argument not supporting all available methods --- src/core/n-strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/n-strings.c b/src/core/n-strings.c index 6c5faa4979..51109d0487 100644 --- a/src/core/n-strings.c +++ b/src/core/n-strings.c @@ -264,7 +264,7 @@ static struct digest { else { // Dispatch file to file-checksum function... REBVAL *func = Find_Word_Value(Lib_Context, SYM_FILE_CHECKSUM); - if (func && IS_FUNCTION(func) && sym > SYM_CRC32 && sym <= SYM_RIPEMD160) { + if (func && IS_FUNCTION(func) && sym > SYM_CRC32 && sym <= SYM_SHA3_512) { if (D_REF(ARG_CHECKSUM_WITH) || D_REF(ARG_CHECKSUM_PART)) Trap0(RE_BAD_REFINES); From 2ba01ead3b5da1ab609fa25a0c675b30e96bb163 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 7 Feb 2024 00:14:42 +0100 Subject: [PATCH 52/60] CHANGE: `unset` value in `any` and `all` is transparent now resolves: https://github.com/Oldes/Rebol-issues/issues/850 resolves: https://github.com/Oldes/Rebol3/discussions/88 --- src/core/n-control.c | 12 ++++++++++-- src/tests/units/conditional-test.r3 | 11 +++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/n-control.c b/src/core/n-control.c index a829f523e6..1774fe045e 100644 --- a/src/core/n-control.c +++ b/src/core/n-control.c @@ -307,12 +307,19 @@ enum { ds = 0; while (index < SERIES_TAIL(block)) { index = Do_Next(block, index, 0); // stack volatile + // ignore unset result + if (IS_UNSET(DS_TOP)) { + DS_DROP; + continue; + } ds = DS_POP; // volatile stack reference if (IS_FALSE(ds)) return R_NONE; + // store the value as a potencial result + DS_RET_VALUE(ds); + // stop precessing if the value was thrown if (THROWN(ds)) break; } - if (ds == 0) return R_TRUE; - return R_TOS1; + return R_RET; } @@ -328,6 +335,7 @@ enum { while (index < SERIES_TAIL(block)) { index = Do_Next(block, index, 0); // stack volatile ds = DS_POP; // volatile stack reference + if (IS_UNSET(ds)) continue; // ignore unset result if (!IS_FALSE(ds)) return R_TOS1; } return R_NONE; diff --git a/src/tests/units/conditional-test.r3 b/src/tests/units/conditional-test.r3 index ae1aeb786f..4bdfd796a7 100644 --- a/src/tests/units/conditional-test.r3 +++ b/src/tests/units/conditional-test.r3 @@ -10,13 +10,13 @@ Rebol [ ===start-group=== "Dealing with unset! value in conditions" --test-- "any" - --assert unset? any [() 2] + --assert 2 = any [() 2] --assert true? any [() 2] --test-- "all" --assert true? all [] --assert true? all [()] --assert 3 = all [() 1 2 3] - --assert unset? all [1 ()] + --assert 1 = all [1 ()] --assert 1 = if all [1 ()][1] --assert 1 = either all [()][1][2] --test-- "any and all" @@ -25,6 +25,13 @@ Rebol [ all [true x: 2 ()] ][ x: 2 * x] --assert x = 4 + ;@@ https://github.com/Oldes/Rebol3/discussions/88 + --assert none? any [] + --assert none? any [()] + --assert 1 = any [() 1] + --assert 1 = all [1 ()] + --assert #[true] = all [] + --assert #[true] = all [()] ===end-group=== ===start-group=== "SWITCH" From ff565f751fca768c158de54ce65c5bfa7a61271e Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 7 Feb 2024 00:18:04 +0100 Subject: [PATCH 53/60] TEST: https://github.com/Oldes/Rebol-issues/issues/850 --- src/tests/units/conditional-test.r3 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tests/units/conditional-test.r3 b/src/tests/units/conditional-test.r3 index 4bdfd796a7..c4eea916ac 100644 --- a/src/tests/units/conditional-test.r3 +++ b/src/tests/units/conditional-test.r3 @@ -25,13 +25,15 @@ Rebol [ all [true x: 2 ()] ][ x: 2 * x] --assert x = 4 + --test-- "unset value transparency in any and all" + ;@@ https://github.com/Oldes/Rebol-issues/issues/850 ;@@ https://github.com/Oldes/Rebol3/discussions/88 --assert none? any [] --assert none? any [()] --assert 1 = any [() 1] --assert 1 = all [1 ()] - --assert #[true] = all [] - --assert #[true] = all [()] + --assert unset? all [] + --assert unset? all [()] ===end-group=== ===start-group=== "SWITCH" From 238ecbcedda7b583ce0d96d4c111dc5d6d1bd330 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 15 Feb 2024 17:47:28 +0100 Subject: [PATCH 54/60] FIX: regression when creating 64 bit vectors resolves: https://github.com/Oldes/Rebol-issues/issues/2590 --- src/core/t-vector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/t-vector.c b/src/core/t-vector.c index 19c56f4fde..c1ff8c302a 100644 --- a/src/core/t-vector.c +++ b/src/core/t-vector.c @@ -446,7 +446,7 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk) ser->tail = len; // !!! another way to do it? // Store info about the vector (could be moved to flags if necessary): - ser->size = (dims << 8) | (type << 3) | (sign << 2) | (bits >> 4); + ser->size = (dims << 8) | (type << 3) | (sign << 2) | (bits >> 4)-1; // bits are zero based value! return ser; } From 695636065bb7876478dbf70e7f5f4560eb986370 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Thu, 15 Feb 2024 17:49:50 +0100 Subject: [PATCH 55/60] FIX: correct fix of regression when creating 64 bit vectors resolves: https://github.com/Oldes/Rebol-issues/issues/2590 --- src/core/t-vector.c | 2 +- src/tests/units/vector-test.r3 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/t-vector.c b/src/core/t-vector.c index c1ff8c302a..f59eef22e4 100644 --- a/src/core/t-vector.c +++ b/src/core/t-vector.c @@ -446,7 +446,7 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk) ser->tail = len; // !!! another way to do it? // Store info about the vector (could be moved to flags if necessary): - ser->size = (dims << 8) | (type << 3) | (sign << 2) | (bits >> 4)-1; // bits are zero based value! + ser->size = (dims << 8) | (type << 3) | (sign << 2) | (bits == 64 ? 3 : bits >> 4); // there are only 2 bits to store the info return ser; } diff --git a/src/tests/units/vector-test.r3 b/src/tests/units/vector-test.r3 index 0cb4ce6719..f41988efbc 100644 --- a/src/tests/units/vector-test.r3 +++ b/src/tests/units/vector-test.r3 @@ -67,6 +67,7 @@ Rebol [ --assert [1 2] = to block! #[u16! [1 2]] --test-- "to-binary vector!" + ;@@ https://github.com/Oldes/Rebol-issues/issues/2590 --assert #{01000200} = to binary! #[u16! [1 2]] --assert #{0100000002000000} = to binary! #[i32! [1 2]] --assert #{0000803F00000040} = to binary! #[f32! [1 2]] From 01a68cfbedebd86fda68ce287efba85a0f199660 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Fri, 16 Feb 2024 08:43:15 +0100 Subject: [PATCH 56/60] FIX: compiler warnings --- src/core/u-xxhash.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/u-xxhash.c b/src/core/u-xxhash.c index 01097e445a..856e0face0 100644 --- a/src/core/u-xxhash.c +++ b/src/core/u-xxhash.c @@ -52,7 +52,7 @@ { // d is data, n is length XXH64_hash_t const hash = XXH3_64bits(d, n); - XXH64_canonicalFromHash(md, hash); + XXH64_canonicalFromHash((XXH64_canonical_t *)md, hash); return md; } /*********************************************************************** @@ -62,7 +62,7 @@ ***********************************************************************/ { XXH32_hash_t const hash = XXH32(d, n, 0); - XXH32_canonicalFromHash(md, hash); + XXH32_canonicalFromHash((XXH32_canonical_t *)md, hash); return md; } /*********************************************************************** @@ -73,7 +73,7 @@ { // d is data, n is length XXH64_hash_t const hash = XXH64(d, n, 0); - XXH64_canonicalFromHash(md, hash); + XXH64_canonicalFromHash((XXH64_canonical_t *)md, hash); return md; } /*********************************************************************** @@ -84,7 +84,7 @@ { // d is data, n is length XXH128_hash_t const hash = XXH128(d, n, 0); - XXH128_canonicalFromHash(md, hash); + XXH128_canonicalFromHash((XXH128_canonical_t *)md, hash); return md; } int XXH3_CtxSize(void) { return sizeof(XXH3_state_t); } @@ -103,10 +103,10 @@ void XXH3_Update( XXH3_state_t *ctx, XXH3_64bits_update( ctx, input, ilen ); } void XXH3_Finish(XXH3_state_t*ctx, - unsigned char output[64] ) + unsigned char output[8] ) { XXH64_hash_t const hash = XXH3_64bits_digest(ctx); - XXH64_canonicalFromHash(output, hash); + XXH64_canonicalFromHash((XXH64_canonical_t *)output, hash); } void XXH32_Starts( XXH32_state_t *ctx ) @@ -121,10 +121,10 @@ void XXH32_Update( XXH32_state_t *ctx, XXH32_update( ctx, input, ilen ); } void XXH32_Finish(XXH32_state_t*ctx, - unsigned char output[64] ) + unsigned char output[4] ) { XXH32_hash_t const hash = XXH32_digest(ctx); - XXH32_canonicalFromHash(output, hash); + XXH32_canonicalFromHash((XXH32_canonical_t *)output, hash); } void XXH64_Starts( XXH64_state_t *ctx ) @@ -139,10 +139,10 @@ void XXH64_Update( XXH64_state_t *ctx, XXH64_update( ctx, input, ilen ); } void XXH64_Finish(XXH64_state_t*ctx, - unsigned char output[64] ) + unsigned char output[8] ) { XXH64_hash_t const hash = XXH64_digest(ctx); - XXH64_canonicalFromHash(output, hash); + XXH64_canonicalFromHash((XXH64_canonical_t *)output, hash); } void XXH128_Starts( XXH3_state_t *ctx ) From 207857c6bc79ff460446a4df3c03106b8f1e4884 Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 17 Feb 2024 12:46:27 +0100 Subject: [PATCH 57/60] TEST: https://github.com/Oldes/Rebol-issues/issues/2587 --- src/tests/units/image-test.r3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/units/image-test.r3 b/src/tests/units/image-test.r3 index 1bc57a49a4..d06ae02a60 100644 --- a/src/tests/units/image-test.r3 +++ b/src/tests/units/image-test.r3 @@ -493,7 +493,7 @@ if value? 'blur [ --test-- "loading JPEG file with an unexpected property type" ;@@ https://github.com/Oldes/Rebol-issues/issues/2587 --assert all [ - img: image? try [load %units/files/issue-2587.jpg] ;; no error! + image? try [img: load %units/files/issue-2587.jpg] ;; no error! img/size = 105x150 ] ] From cb6430669c10a487eca20feea45fa04c9334c9dc Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 17 Feb 2024 12:51:36 +0100 Subject: [PATCH 58/60] TEST: https://github.com/Oldes/Rebol-issues/issues/1734 --- src/tests/units/evaluation-test.r3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/units/evaluation-test.r3 b/src/tests/units/evaluation-test.r3 index 62d664e0fd..587bfd0d11 100644 --- a/src/tests/units/evaluation-test.r3 +++ b/src/tests/units/evaluation-test.r3 @@ -806,8 +806,8 @@ Rebol [ --assert a == 1 --assert 100 = catch/quit [++ a quit/return 100 ++ a] --assert a == 2 - --assert 0 = call/shell/wait join system/options/boot { --do "quit"} - --assert 100 = call/shell/wait join system/options/boot { --do "quit/return 100"} + --assert 0 = call/shell/wait append to-local-file system/options/boot { --do "quit"} + --assert 100 = call/shell/wait append to-local-file system/options/boot { --do "quit/return 100"} --test-- "nested catch" a: 0 --assert 'x = catch [++ a catch/quit [++ a quit a: 0] a: a * 2 throw 'x a: a * 100] From 3c2b93afa872334effe9c840813ed789ce1dbd0c Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 17 Feb 2024 13:03:47 +0100 Subject: [PATCH 59/60] CHANGE: **Switching map and construction syntax** `map!` values now use syntax like: `#[key: value]` construction syntax now looks like: `#(true)` or `#(i32! [1 2 3])` The included [`map-conv.reb` script](https://github.com/Oldes/Rebol3/blob/master/make/tools/map-conv.reb) can be used for converting existing code. resolves: https://github.com/Oldes/Rebol-issues/issues/2589 --- .version | 2 +- make/r3-view.rc | 8 +- make/r3.rc | 8 +- make/rebol3.nest | 2 +- make/tools/make-boot.reb | 16 +- make/tools/map-conv.reb | 120 ++++++ make/tools/utils.reb | 13 +- src/boot/natives.reb | 2 +- src/boot/sysobj.reb | 30 +- src/boot/types.reb | 2 +- src/boot/words.reb | 4 +- src/core/l-scan.c | 10 +- src/core/l-types.c | 2 +- src/core/s-mold.c | 40 +- src/mezz/base-constants.reb | 2 +- src/mezz/base-files.reb | 2 +- src/mezz/base-series.reb | 2 +- src/mezz/codec-bbcode.reb | 12 +- src/mezz/codec-html-entities.reb | 4 +- src/mezz/codec-json.reb | 14 +- src/mezz/codec-mime-field.reb | 6 +- src/mezz/codec-mime-types.reb | 2 +- src/mezz/codec-pdf.reb | 38 +- src/mezz/codec-safe.reb | 2 +- src/mezz/mezz-banner.reb | 5 +- src/mezz/mezz-save.reb | 2 +- src/mezz/prot-http.reb | 6 +- src/mezz/prot-mail.reb | 8 +- src/mezz/sys-load.reb | 2 +- src/mezz/sys-ports.reb | 10 +- src/modules/httpd.reb | 10 +- src/modules/munge3.reb | 3 +- src/modules/spotify.reb | 8 +- src/modules/unicode-utils.reb | 4 +- src/modules/webdriver.reb | 4 +- src/os/win32/sys-codecs.cpp | 15 +- src/tests/test-extension-triangulate.r3 | 14 +- src/tests/test-httpd.r3 | 2 +- src/tests/units/bincode-test.r3 | 4 +- src/tests/units/bitset-test.r3 | 30 +- src/tests/units/codecs-test-pdf.r3 | 38 +- src/tests/units/codecs-test.r3 | 8 +- src/tests/units/conditional-test.r3 | 10 +- src/tests/units/copy-test.r3 | 50 +-- src/tests/units/crash-test.r3 | 4 +- src/tests/units/crypt-port-ccm-test.r3 | 96 ++--- src/tests/units/crypt-port-test.r3 | 38 +- src/tests/units/crypt-test.r3 | 2 +- src/tests/units/datatype-test.r3 | 22 +- src/tests/units/date-test.r3 | 36 +- src/tests/units/decimal-test.r3 | 2 +- src/tests/units/delect-test.r3 | 4 +- src/tests/units/dh-test.r3 | 4 +- src/tests/units/error-test.r3 | 4 +- src/tests/units/evaluation-test.r3 | 24 +- src/tests/units/func-test.r3 | 46 +-- src/tests/units/handle-test.r3 | 2 +- src/tests/units/image-test.r3 | 30 +- src/tests/units/lexer-test.r3 | 176 ++++----- src/tests/units/load-test.r3 | 2 +- src/tests/units/make-test.r3 | 478 ++++++++++++------------ src/tests/units/map-test.r3 | 118 +++--- src/tests/units/module-test.r3 | 10 +- src/tests/units/mold-test.r3 | 62 +-- src/tests/units/object-test.r3 | 18 +- src/tests/units/parse-test.r3 | 22 +- src/tests/units/rsa-test.r3 | 4 +- src/tests/units/series-test.r3 | 136 +++---- src/tests/units/typeset-test.r3 | 4 +- src/tests/units/vector-test.r3 | 304 +++++++-------- 70 files changed, 1183 insertions(+), 1041 deletions(-) create mode 100644 make/tools/map-conv.reb diff --git a/.version b/.version index d0adf2c9ce..7ccd8d4468 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -3.15.1 \ No newline at end of file +3.16.0 \ No newline at end of file diff --git a/make/r3-view.rc b/make/r3-view.rc index 61f0c59368..dc61901275 100644 --- a/make/r3-view.rc +++ b/make/r3-view.rc @@ -1,20 +1,20 @@ 101 ICON "icon/r3.ico" 1 VERSIONINFO -FILEVERSION 3,15,1,0 -PRODUCTVERSION 3,15,1,0 +FILEVERSION 3,16,0,0 +PRODUCTVERSION 3,16,0,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "Rebol Console" - VALUE "FileVersion", "3.15" + VALUE "FileVersion", "3.16" VALUE "InternalName", "Rebol 3 (Oldes branch)" VALUE "LegalCopyright", "2012 REBOL Technologies" VALUE "OriginalFilename", "Rebol.exe" VALUE "ProductName", "Rebol/View" - VALUE "ProductVersion", "3.15" + VALUE "ProductVersion", "3.16" END END BLOCK "VarFileInfo" diff --git a/make/r3.rc b/make/r3.rc index aa6f7b4403..f0af15ab03 100644 --- a/make/r3.rc +++ b/make/r3.rc @@ -1,20 +1,20 @@ 101 ICON "icon/r3.ico" 1 VERSIONINFO -FILEVERSION 3,15,1,0 -PRODUCTVERSION 3,15,1,0 +FILEVERSION 3,16,0,0 +PRODUCTVERSION 3,16,0,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "Rebol Console" - VALUE "FileVersion", "3.15" + VALUE "FileVersion", "3.16" VALUE "InternalName", "Rebol 3 (Oldes branch)" VALUE "LegalCopyright", "2012 REBOL Technologies" VALUE "OriginalFilename", "Rebol.exe" VALUE "ProductName", "Rebol" - VALUE "ProductVersion", "3.15" + VALUE "ProductVersion", "3.16" END END BLOCK "VarFileInfo" diff --git a/make/rebol3.nest b/make/rebol3.nest index a06c608bb3..790208a510 100644 --- a/make/rebol3.nest +++ b/make/rebol3.nest @@ -18,7 +18,7 @@ temp: %make/tmp/ stack-size: 4194304 ;= 4MB (4 * 1024 * 1024) optimize: 2 -version: 3.15.1 +version: 3.16.0 #if Linux? [ defines: TO_LINUX ] #if macOS? [ defines: TO_MACOS ] diff --git a/make/tools/make-boot.reb b/make/tools/make-boot.reb index 73e32b1285..dbc6066ccf 100644 --- a/make/tools/make-boot.reb +++ b/make/tools/make-boot.reb @@ -3,7 +3,7 @@ REBOL [ Title: "Make primary boot files" Rights: { Copyright 2012 REBOL Technologies - Copyright 2012-2023 Rebol Open Source Contributors + Copyright 2012-2024 Rebol Open Source Contributors REBOL is a trademark of REBOL Technologies } License: { @@ -38,7 +38,7 @@ src: root-dir/src/core Title: {REBOL Copyright 2012 REBOL Technologies -Copyright 2012-2021 Rebol Open Source Contributors +Copyright 2012-2024 Rebol Open Source Contributors REBOL is a trademark of REBOL Technologies Licensed under the Apache License, Version 2.0 } @@ -924,7 +924,7 @@ foreach section [boot-base boot-sys boot-mezz] [ compose [ sys/load-module/delay ( append - mold/only compose/deep/only [ + map-conv-if-needed mold/only compose/deep/only [ Rebol [ Version: (any [select hdr 'version 0.0.0]) Title: (select hdr 'title) @@ -935,7 +935,7 @@ foreach section [boot-base boot-sys boot-mezz] [ Needs: (select hdr 'needs) ] ] - mold/only code + map-conv-if-needed mold/only code ) ] ][ @@ -976,7 +976,7 @@ foreach file first mezz-files [ compose [ sys/load-module/delay ( append - mold/only compose/deep/only [ + map-conv-if-needed mold/only compose/deep/only [ Rebol [ Version: (any [select hdr 'version 0.0.0]) Title: (select hdr 'title) @@ -987,7 +987,7 @@ foreach file first mezz-files [ Needs: (select hdr 'needs) ] ] - mold/only code + map-conv-if-needed mold/only code ) ] ][ @@ -1093,13 +1093,13 @@ boot-task: load-boot %task.reb boot-ops: load-boot %ops.reb ;boot-script: load-boot %script.reb -write-generated gen-dir/gen-boot-code.reb mold reduce sections +write-generated gen-dir/gen-boot-code.reb entab mold reduce sections data: mold reduce sections insert data reduce ["; Copyright (C) REBOL Technologies " now newline] insert tail data make char! 0 ; scanner requires zero termination -data: to binary! data +data: to binary! map-conv-if-needed data comp-data: compress/level data 'zlib 9 emit [ diff --git a/make/tools/map-conv.reb b/make/tools/map-conv.reb new file mode 100644 index 0000000000..8f7dd858e8 --- /dev/null +++ b/make/tools/map-conv.reb @@ -0,0 +1,120 @@ +REBOL [ + Title: "Map and construction syntax literal syntax migration script" + Author: "Oldes" + File: %map-conv.reb + Assert: [ + probe "map: #[a: 1 b: #(none)]" == map-conv {map: #(a: 1 b: #[none])} + probe "blk: [#(none) #(true)]" == map-conv {blk: [#[none] #[true]]} + probe "vec: #(uint8! [1 2 3])" == map-conv {vec: #[uint8! [1 2 3]]} + probe "m: #[a: #(none)]#[b: 1]" == map-conv {m: #(a: #[none])#(b: 1)} + probe "#[a: #[b: #(false)]]" == map-conv {#(a: #(b: #[false]))} + probe "#{} #[unset!]" == map-conv {#{} #(unset!)} + probe {#[unset] #"^{" #[true]} == map-conv {#(unset) #"^{" #(true)} + probe {#[unset] "^{" #[true]} == map-conv {#(unset) "^{" #(true)} + probe "#[unset] {^^{} #[true]" == map-conv "#(unset) {^^{} #(true)" + ] + Note: "The parser is simplified! Content inside strings and comments is ignored!" +] + +map-conv: function/with [ + "Swaps map! and construction syntax" + data [binary! string! file!] "(modified)" +][ + either file? data [ + either dir? data [ + process-dir data + ][ process-file data ] + ][ + swap-map-cs data + ] +][ + pos: none + ch_ignore: complement charset {[](){};#"} + ch_ignore_str1: complement charset "^^{}" + ch_ignore_str2: complement charset {^^"} + rl_paren: [#"(" rl_swap #")"] + rl_block: [#"[" rl_swap #"]"] + + rl_in_string1: [any [some ch_ignore_str1 | #"^^" skip | rl_string1]] + rl_in_string2: [any [some ch_ignore_str2 | #"^^" skip]] + rl_string1: [#"{" rl_in_string1 #"}"] + rl_string2: [#"^"" rl_in_string2 #"^""] + rl_comment: [#";" [to LF | to end]] + + rl_swap: [ + any [ + some ch_ignore + | rl_comment + | rl_block + | rl_paren + | rl_string1 + | rl_string2 + | #"#" pos: [ + ahead #"[" (append cons_s index? pos) rl_block pos: (append append cons take/last cons_s index? pos) + | ahead #"(" (append maps_s index? pos) rl_paren pos: (append append maps take/last maps_s index? pos) + | ahead #"{" thru #"}" ;; ignore binaries + | #"^"" [#"^^" #"^"" #"^"" | thru #"^""] ;; ignore chars + | skip + ] + | end + ] + ] + + cons: make block! 1000 + maps: make block! 1000 + + ;; stacks.. + maps_s: make block! 1000 + cons_s: make block! 1000 + + process-dir: function [path [file!]][ + foreach file read path [ + if dir? file [process-dir path/:file] + all [ + find [%.reb %.r3] suffix? file + process-file path/:file + ] + ] + ] + process-file: function [file [file!]][ + try/with [ + print [as-green "File:" as-yellow file] + data: swap-map-cs read file + num-maps: (length? maps) / 2 + num-cons: (length? cons) / 2 + if any [num-maps > 0 num-cons > 0][ + print ["maps:" as-yellow num-maps "cons:" as-yellow num-cons] + write file data + ] + ][ + print as-purple "File conversion failed!" + print system/state/last-error + ] + ] + + swap-map-cs: func[data][ + clear cons + clear maps + clear cons_s + clear maps_s + if binary? data [data: to string! data] + unless parse data rl_swap [ + print as-purple "File not fully parsed so not modified!" + return data + ] + ;?? cons + foreach [s e] cons [ + change at data s #"(" + change at data e - 1 #")" + ] + ;?? maps + foreach [s e] maps [ + change at data s #"[" + change at data e - 1 #"]" + ] + ;print data + data + ] +] + + diff --git a/make/tools/utils.reb b/make/tools/utils.reb index b3943c115d..a46a3aa043 100644 --- a/make/tools/utils.reb +++ b/make/tools/utils.reb @@ -3,9 +3,14 @@ REBOL [ Title: "Common make-* code" ] - +do %map-conv.reb ;-- UTILITIES ---------------------------------------------------------- +needs-map-syntax-swap?: map? transcode/one/error "#()" +map-conv-if-needed: func[data][ + if needs-map-syntax-swap? [map-conv data] + data +] print-title: func[msg][if block? msg [msg: reform msg] print rejoin ["^/ [pre-make.r3] ^[[1;35m" msg "^[[m"]] print-info: func[msg][if block? msg [msg: reform msg] print rejoin [ " [pre-make.r3] ^[[0;32m" msg "^[[m"]] @@ -19,6 +24,7 @@ read-file: func[file [file!]][ load-file: func[file [file!] /header][ the-file: find/tail file root-dir ; shortened version print rejoin [" [pre-make.r3] ^[[0;36mProcessing: ^[[0;31m" the-file "^[[m"] + if needs-map-syntax-swap? [ file: map-conv read file] try/except [either header [load/header/all file][ load file ]][ sys/log/error 'pre-make.r3 system/state/last-error quit/return 3 @@ -29,12 +35,17 @@ load-file: func[file [file!] /header][ write-generated: func[file data][ write file data print-more ["Generated:^[[33m" to-local-file file] + if all [ + needs-map-syntax-swap? + find [%.reb %.r3] suffix? file + ][ map-conv file ] ] save-generated: func[file data /header hdr][ either header [ save/header file data hdr ][ save file data ] print-more ["Generated:^[[33m" to-local-file file] + if needs-map-syntax-swap? [ map-conv file] ] diff --git a/src/boot/natives.reb b/src/boot/natives.reb index 92de92c3ce..c9215c42b8 100644 --- a/src/boot/natives.reb +++ b/src/boot/natives.reb @@ -3,7 +3,7 @@ REBOL [ Title: "Native function specs" Rights: { Copyright 2012 REBOL Technologies - Copyright 2012-2021 Rebol Open Source Developers + Copyright 2012-2024 Rebol Open Source Developers REBOL is a trademark of REBOL Technologies } License: { diff --git a/src/boot/sysobj.reb b/src/boot/sysobj.reb index 5e819683de..beaf7677ef 100644 --- a/src/boot/sysobj.reb +++ b/src/boot/sysobj.reb @@ -3,7 +3,7 @@ REBOL [ Title: "System object" Rights: { Copyright 2012 REBOL Technologies - Copyright 2012-2023 Rebol Open Source Contributors + Copyright 2012-2024 Rebol Open Source Contributors REBOL is a trademark of REBOL Technologies } License: { @@ -26,7 +26,7 @@ build: object [os: os-version: abi: sys: arch: libc: vendor: target: compiler user: construct [ name: none - data: #() + data: #[] ] options: object [ ; Options supplied to REBOL during startup @@ -61,13 +61,13 @@ options: object [ ; Options supplied to REBOL during startup ; verbosity of logs per service (codecs, schemes) ; 0 = nothing; 1 = info; 2 = more; 3 = debug - log: #[map! [ + log: #[ rebol: 1 http: 1 tls: 1 zip: 1 tar: 1 - ]] + ] domain-name: none ; Specifies system's domain name (used in SMTP scheme so far) ] @@ -95,18 +95,18 @@ catalog: object [ secure-min secure-max trace halt cgi boot-level no-window ] bitsets: object [ - crlf: #[bitset! #{0024}] ;charset "^/^M" - space: #[bitset! #{0040000080}] ;charset " ^-" - whitespace: #[bitset! #{0064000080}] ;charset "^/^M^- " - numeric: #[bitset! #{000000000000FFC0}] ;0-9 - alpha: #[bitset! #{00000000000000007FFFFFE07FFFFFE0}] ;A-Z a-z - alpha-numeric: #[bitset! #{000000000000FFC07FFFFFE07FFFFFE0}] ;A-Z a-z 0-9 - hex-digits: #[bitset! #{000000000000FFC07E0000007E}] ;A-F a-f 0-9 - plus-minus: #[bitset! #{000000000014}] ;charset "+-" + crlf: #(bitset! #{0024}) ;charset "^/^M" + space: #(bitset! #{0040000080}) ;charset " ^-" + whitespace: #(bitset! #{0064000080}) ;charset "^/^M^- " + numeric: #(bitset! #{000000000000FFC0}) ;0-9 + alpha: #(bitset! #{00000000000000007FFFFFE07FFFFFE0}) ;A-Z a-z + alpha-numeric: #(bitset! #{000000000000FFC07FFFFFE07FFFFFE0}) ;A-Z a-z 0-9 + hex-digits: #(bitset! #{000000000000FFC07E0000007E}) ;A-F a-f 0-9 + plus-minus: #(bitset! #{000000000014}) ;charset "+-" ; chars which does not have to be url-encoded: - uri: #[bitset! #{000000005BFFFFF5FFFFFFE17FFFFFE2}] ;A-Z a-z 0-9 !#$&'()*+,-./:;=?@_~ - uri-component: #[bitset! #{0000000041E6FFC07FFFFFE17FFFFFE2}] ;A-Z a-z 0-9 !'()*-._~ - quoted-printable: #[bitset! #{FFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFF}] + uri: #(bitset! #{000000005BFFFFF5FFFFFFE17FFFFFE2}) ;A-Z a-z 0-9 !#$&'()*+,-./:;=?@_~ + uri-component: #(bitset! #{0000000041E6FFC07FFFFFE17FFFFFE2}) ;A-Z a-z 0-9 !'()*-._~ + quoted-printable: #(bitset! #{FFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFF}) ] checksums: [ ; will be filled on boot from `Init_Crypt` in `n-crypt.c diff --git a/src/boot/types.reb b/src/boot/types.reb index d494b4b7a1..9e8008145b 100644 --- a/src/boot/types.reb +++ b/src/boot/types.reb @@ -25,7 +25,7 @@ REBOL [ ; Mold - mold format: - self, + type, * typeclass ; Form - form format: above, and f* for special form functions ; Path - it supports various path forms (* for same as typeclass) -; Make - It can be made with #[datatype] method +; Make - It can be made with #(datatype) method ; Datatype Evaluator Typeclass Mold Form Path Make Typesets ;------------------------------------------------------------------------------ diff --git a/src/boot/words.reb b/src/boot/words.reb index 40e71a32db..bbdd2a2926 100644 --- a/src/boot/words.reb +++ b/src/boot/words.reb @@ -3,7 +3,7 @@ REBOL [ Title: "Canonical words" Rights: { Copyright 2012 REBOL Technologies - Copyright 2012-2022 Rebol Open Source Contributors + Copyright 2012-2024 Rebol Open Source Contributors REBOL is a trademark of REBOL Technologies } License: { @@ -28,7 +28,7 @@ any-object! any-block! ;- numeric types (used for "short" vector! construction) -;- like: #[u8! 4] which is same like: make vector! [unsigned integer! 8 4] +;- like: #(u8! 4) which is same like: make vector! [unsigned integer! 8 4] ; these numeric files are used in l-types.c and t-vector.c sources ; and can be used for future struct! and routine! implementations i8! diff --git a/src/core/l-scan.c b/src/core/l-scan.c index 5f3b9e9988..9fcfa80348 100644 --- a/src/core/l-scan.c +++ b/src/core/l-scan.c @@ -1203,7 +1203,7 @@ | LEX_FLAG(LEX_SPECIAL_TICK) | LEX_FLAG(LEX_SPECIAL_WORD)))) return -TOKEN_INTEGER; */ /* if (HAS_LEX_FLAG(flags, LEX_SPECIAL_PERIOD)) return TOKEN_BYTES; */ - if (*cp == '[') { + if (*cp == '(') { scan_state->end = ++cp; return TOKEN_CONSTRUCT; } @@ -1238,7 +1238,7 @@ return -TOKEN_BINARY; } } - if (*cp == '(') { + if (*cp == '[') { scan_state->end = ++cp; return TOKEN_MAP; } @@ -1799,9 +1799,9 @@ extern REBSER *Scan_Full_Block(SCAN_STATE *scan_state, REBYTE mode_char); break; case TOKEN_CONSTRUCT: - block = Scan_Full_Block(scan_state, ']'); + block = Scan_Full_Block(scan_state, ')'); value = BLK_TAIL(emitbuf); - // make sure that there was not an error... transcode "#[" + // make sure that there was not an error... transcode "#(" if (!IS_ERROR(value)){ emitbuf->tail++; // Protect the block from GC if (!Construct_Value(value, block)) { @@ -1818,7 +1818,7 @@ extern REBSER *Scan_Full_Block(SCAN_STATE *scan_state, REBYTE mode_char); break; case TOKEN_MAP: - block = Scan_Block(scan_state, ')'); + block = Scan_Block(scan_state, ']'); // (above line could have realloced emitbuf) ep = scan_state->end; value = BLK_TAIL(emitbuf); diff --git a/src/core/l-types.c b/src/core/l-types.c index 6a4b603f17..1181a4ca7c 100644 --- a/src/core/l-types.c +++ b/src/core/l-types.c @@ -1118,7 +1118,7 @@ bad_hex: Trap0(RE_INVALID_CHARS); ** in unevaluated source code format. The format of the datatype ** constructor is: ** -** #[datatype! | keyword spec] +** #(datatype! | keyword spec) ** ** The first item is a datatype word or NONE, FALSE or TRUE. The ** second part is a specification for the datatype, as a basic diff --git a/src/core/s-mold.c b/src/core/s-mold.c index 7b913790eb..fc7b71eea6 100644 --- a/src/core/s-mold.c +++ b/src/core/s-mold.c @@ -125,8 +125,8 @@ enum { break; case '+': // Add #[ if mold/all if (GET_MOPT(mold, MOPT_MOLD_ALL)) { - Append_Bytes(series, "#["); - ender = ']'; + Append_Bytes(series, "#("); + ender = ')'; } break; case 'D': // Datatype symbol: #[type @@ -206,7 +206,7 @@ enum { ** ***********************************************************************/ { - Emit(mold, GET_MOPT(mold, MOPT_MOLD_ALL) ? "#[T " : "make T ", value); + Emit(mold, GET_MOPT(mold, MOPT_MOLD_ALL) ? "#(T " : "make T ", value); } @@ -218,7 +218,7 @@ enum { ** ***********************************************************************/ { - if (GET_MOPT(mold, MOPT_MOLD_ALL)) Append_Byte(mold->series, ']'); + if (GET_MOPT(mold, MOPT_MOLD_ALL)) Append_Byte(mold->series, ')'); } @@ -235,7 +235,7 @@ enum { Append_Byte(mold->series, ' '); Append_Int(mold->series, VAL_INDEX(value)+1); } - if (GET_MOPT(mold, MOPT_MOLD_ALL)) Append_Byte(mold->series, ']'); + if (GET_MOPT(mold, MOPT_MOLD_ALL)) Append_Byte(mold->series, ')'); } @@ -550,7 +550,7 @@ STOID Mold_Handle(REBVAL *value, REB_MOLD *mold) { const REBYTE *name = VAL_HANDLE_NAME(value); if (name != NULL) { - Append_Bytes(mold->series, "#[handle! "); + Append_Bytes(mold->series, "#(handle! "); Append_Bytes(mold->series, cs_cast(name)); if (IS_CONTEXT_HANDLE(value)) { if (!IS_USED_HOB(VAL_HANDLE_CTX(value))) @@ -568,7 +568,7 @@ STOID Mold_Handle(REBVAL *value, REB_MOLD *mold) } } } - Append_Byte(mold->series, ']'); + Append_Byte(mold->series, ')'); } else { Emit(mold, "+T", value); @@ -629,7 +629,7 @@ STOID Mold_All_Constr_String(REBVAL *value, REB_MOLD *mold) // The string that is molded for /all option: REBVAL val; // prep... - Emit(mold, "#[T ", value); // #[file! part + Emit(mold, "#(T ", value); // #(file! part // string... val = *value; VAL_INDEX(&val) = 0; @@ -640,7 +640,7 @@ STOID Mold_All_Constr_String(REBVAL *value, REB_MOLD *mold) Append_Byte(mold->series, ' '); Append_Int(mold->series, VAL_INDEX(value)+1); } - Append_Byte(mold->series, ']'); + Append_Byte(mold->series, ')'); } STOID Mold_Ref(REBVAL *value, REB_MOLD *mold) @@ -758,7 +758,7 @@ STOID Mold_Block(REBVAL *value, REB_MOLD *mold, REBFLG molded) if (all || (over && !IS_BLOCK(value) && !IS_PAREN(value))) { SET_FLAG(mold->opts, MOPT_MOLD_ALL); - Pre_Mold(value, mold); // #[block! part + Pre_Mold(value, mold); // #(block! part //if (over) Append_Bytes(mold->series, "[]"); //else Mold_Block_Series(mold, VAL_SERIES(value), 0, 0); @@ -889,7 +889,7 @@ STOID Mold_Typeset(REBVAL *value, REB_MOLD *mold, REBFLG molded) REBINT n; if (molded) { - Pre_Mold(value, mold); // #[typeset! or make typeset! + Pre_Mold(value, mold); // #(typeset! or make typeset! Append_Byte(mold->series, '['); } @@ -933,16 +933,16 @@ STOID Mold_Map(REBVAL *value, REB_MOLD *mold, REBFLG molded) // Prevent endless mold loop: if (Find_Same_Block(MOLD_LOOP, value) > 0) { - Append_Bytes(mold->series, "#(...)"); + Append_Bytes(mold->series, "#[...]"); return; } Append_Val(MOLD_LOOP, value); if (molded) { if (all) { - Emit(mold, "#[T [", value); + Emit(mold, "#(T [", value); } else { - Append_Bytes(mold->series, "#("); + Append_Bytes(mold->series, "#["); } } @@ -967,7 +967,7 @@ STOID Mold_Map(REBVAL *value, REB_MOLD *mold, REBFLG molded) if (molded) { if(indented && count>0) New_Indented_Line(mold); - Append_Byte(mold->series, all ? ']' : ')'); + Append_Byte(mold->series, ']'); } End_Mold(mold); @@ -1235,7 +1235,7 @@ STOID Mold_Error(REBVAL *value, REB_MOLD *mold, REBFLG molded) case REB_EMAIL: case REB_URL: if (VAL_LEN(value) == 0) { - Append_Bytes(ser, VAL_TYPE(value) == REB_EMAIL ? "#[email! \"\"]" : "#[url! \"\"]"); + Append_Bytes(ser, VAL_TYPE(value) == REB_EMAIL ? "#(email! \"\")" : "#(url! \"\")"); break; } Mold_Url(value, mold); @@ -1254,9 +1254,9 @@ STOID Mold_Error(REBVAL *value, REB_MOLD *mold, REBFLG molded) case REB_BITSET: // // uses always construction syntax - // Emit(mold, "#[T ", value); + // Emit(mold, "#(T ", value); // Mold_Bitset(value, mold); - // Append_Byte(mold->series, ']'); + // Append_Byte(mold->series, ')'); // break; // Above code makes some problem when preprocessing Rebol source! // So reverting back to the old result... @@ -1423,10 +1423,10 @@ STOID Mold_Error(REBVAL *value, REB_MOLD *mold, REBFLG molded) break; case REB_UNSET: - if(molded) Append_Bytes(ser,"#[unset]"); + if(molded) Append_Bytes(ser,"#(unset)"); break; case REB_END: - if(molded) Append_Bytes(ser,"#[end]"); + if(molded) Append_Bytes(ser,"#(end)"); break; default: Crash(RP_DATATYPE+5, VAL_TYPE(value)); diff --git a/src/mezz/base-constants.reb b/src/mezz/base-constants.reb index 9d9e2fa8d5..a590e06fb1 100644 --- a/src/mezz/base-constants.reb +++ b/src/mezz/base-constants.reb @@ -51,7 +51,7 @@ dot: #"." dbl-quote: #"^"" ;-- Bitset constants -whitespace: #[bitset! #{0064000080}] ;= charset [#" " #"^-" #"^/" #"^M"] +whitespace: #(bitset! #{0064000080}) ;= charset [#" " #"^-" #"^/" #"^M"] ;-- Function synonyms: q: :quit diff --git a/src/mezz/base-files.reb b/src/mezz/base-files.reb index 129c5545ab..f4df296c2b 100644 --- a/src/mezz/base-files.reb +++ b/src/mezz/base-files.reb @@ -46,7 +46,7 @@ suffix?: func [ /local end ][ either all [ - url? path end: find path #[bitset! #{0000000010000001}] ; "?#" + url? path end: find path #(bitset! #{0000000010000001}) ; "?#" ][ all [ path: find/reverse end #"." diff --git a/src/mezz/base-series.reb b/src/mezz/base-series.reb index 3a06a7cd78..e82cc869d0 100644 --- a/src/mezz/base-series.reb +++ b/src/mezz/base-series.reb @@ -54,7 +54,7 @@ ellipsize: func [ /local chars ][ if one-line [ - chars: #[bitset! [not bits #{0024}]] + chars: #(bitset! [not bits #{0024}]) parse str [ any [ some chars diff --git a/src/mezz/codec-bbcode.reb b/src/mezz/codec-bbcode.reb index 206de4e0db..0c33031508 100644 --- a/src/mezz/codec-bbcode.reb +++ b/src/mezz/codec-bbcode.reb @@ -31,12 +31,12 @@ tmp: pos: none ;- charsets & rules - ;-------------------- -ch_space: #[bitset! #{7FFFFFFF800000000000000000000001}] ; charset [#"^A" - #" " #"^(7F)"] -ch_normal: #[bitset! [not bits #{002400000000000800000010}]] ; complement charset "[<^M^/" -ch_attribute: #[bitset! [not bits #{000000002100000A00000004}]] ; complement charset {"'<>]} -ch_attribute1: #[bitset! [not bits #{000000000100000A00000004}]] ; complement charset {'<>]} -ch_attribute2: #[bitset! [not bits #{000000002000000A00000004}]] ; complement charset {"<>]} -ch_attribute3: #[bitset! [not bits #{000000008000000A00000004}]] ; complement charset { <>]} +ch_space: #(bitset! #{7FFFFFFF800000000000000000000001}) ; charset [#"^A" - #" " #"^(7F)"] +ch_normal: #(bitset! [not bits #{002400000000000800000010}]) ; complement charset "[<^M^/" +ch_attribute: #(bitset! [not bits #{000000002100000A00000004}]) ; complement charset {"'<>]} +ch_attribute1: #(bitset! [not bits #{000000000100000A00000004}]) ; complement charset {'<>]} +ch_attribute2: #(bitset! [not bits #{000000002000000A00000004}]) ; complement charset {"<>]} +ch_attribute3: #(bitset! [not bits #{000000008000000A00000004}]) ; complement charset { <>]} ch_digits: charset [#"0" - #"9"] ch_hexa: charset [#"a" - #"f" #"A" - #"F" #"0" - #"9"] ch_name: charset [#"a" - #"z" #"A" - #"Z" #"*" #"0" - #"9"] diff --git a/src/mezz/codec-html-entities.reb b/src/mezz/codec-html-entities.reb index a35f84aee5..9bf75678b1 100644 --- a/src/mezz/codec-html-entities.reb +++ b/src/mezz/codec-html-entities.reb @@ -18,7 +18,7 @@ Rebol [ } ] -html-entities: #[map! [ +html-entities: #[ ;@@ https://eastmanreference.com/list-of-html-entity-names-and-numbers ;-- Punctuation, programming, and other common symbols "lt" #"^(3C)" ; 60 Open tag @@ -272,7 +272,7 @@ html-entities: #[map! [ "zwj" #"^(200D)" ; 8205 Zero width joiner "lrm" #"^(200E)" ; 8206 Left-to-right mark "rlm" #"^(200F)" ; 8207 Right-to-left mark -]] +] any-except-&: complement charset "&" alphanum: charset [#"0" - #"9" #"a" - #"z" #"A" - #"Z"] diff --git a/src/mezz/codec-json.reb b/src/mezz/codec-json.reb index 0eefc3c701..27d3a5aa00 100644 --- a/src/mezz/codec-json.reb +++ b/src/mezz/codec-json.reb @@ -118,12 +118,12 @@ ws: system/catalog/bitsets/whitespace ws*: [any ws] ws+: [some ws] sep: [ws* #"," ws*] ; JSON value separator -non-zero-digit: #[bitset! #{0000000000007FC0}] ;= charset "123456789" +non-zero-digit: #(bitset! #{0000000000007FC0}) ;= charset "123456789" ; Unescaped chars (NOT creates a virtual bitset) -chars: #[bitset! [not bits #{FFFFFFFF2000000000000008}]] ;=charset [not {\"} #"^@"-#"^_"] +chars: #(bitset! [not bits #{FFFFFFFF2000000000000008}]) ;=charset [not {\"} #"^@"-#"^_"] ; chars allowed in Rebol word! values - note that we don't allow < and > at all even though they are somewhat valid in word! -not-word-char: #[bitset! #{00640000BCC9003A8000001E000000140000000080}] ;=charset {/\^^,[](){}"#%$@:;^/^(00A0) ^-^M<>} +not-word-char: #(bitset! #{00640000BCC9003A8000001E000000140000000080}) ;=charset {/\^^,[](){}"#%$@:;^/^(00A0) ^-^M<>} word-1st: complement append union not-word-char digit #"'" word-char: complement not-word-char @@ -291,7 +291,7 @@ load-json: func [ indent: none indent-level: 0 normal-chars: none -escapes: #[map! [ +escapes: #[ #"^"" {\"} #"\" "\\" #"^H" "\b" @@ -299,7 +299,7 @@ escapes: #[map! [ #"^/" "\n" #"^M" "\r" #"^-" "\t" -]] +] init-state: func [ind ascii?][ indent: ind @@ -307,10 +307,10 @@ init-state: func [ind ascii?][ ; 34 is double quote " ; 92 is backslash \ normal-chars: either ascii? [ - #[bitset! #{00000000DFFFFFFFFFFFFFF7FFFFFFFF}] + #(bitset! #{00000000DFFFFFFFFFFFFFF7FFFFFFFF}) ;= charset [32 33 35 - 91 93 - 127] ][ - #[bitset! [not bits #{FFFFFFFF2000000000000008}]] + #(bitset! [not bits #{FFFFFFFF2000000000000008}]) ;= complement charset [0 - 31 34 92] ] ] diff --git a/src/mezz/codec-mime-field.reb b/src/mezz/codec-mime-field.reb index 418f2e3a07..d768bc4b23 100644 --- a/src/mezz/codec-mime-field.reb +++ b/src/mezz/codec-mime-field.reb @@ -58,7 +58,7 @@ register-codec [ to data output ][ ch-crlf: system/catalog/bitsets/crlf - ch-crlf=: #[bitset! #{0024000000000004}] ;charset "^/^M=" + ch-crlf=: #(bitset! #{0024000000000004}) ;charset "^/^M=" ch-space: system/catalog/bitsets/space qp-decode: :codecs/quoted-printable/decode ] @@ -93,7 +93,7 @@ register-codec [ take/part/last out 3 ; removed the last CRLFSP chars to data out ][ - safe-chars: #[bitset! #{004000008000FFC07FFFFFE07FFFFFE0}] ;= alpha-numeric + space - key-chars: #[bitset! #{000000000004FFC07FFFFFE17FFFFFE0}] + safe-chars: #(bitset! #{004000008000FFC07FFFFFE07FFFFFE0}) ;= alpha-numeric + space + key-chars: #(bitset! #{000000000004FFC07FFFFFE17FFFFFE0}) ] ] \ No newline at end of file diff --git a/src/mezz/codec-mime-types.reb b/src/mezz/codec-mime-types.reb index 19475f9700..8d5017862e 100644 --- a/src/mezz/codec-mime-types.reb +++ b/src/mezz/codec-mime-types.reb @@ -15,7 +15,7 @@ REBOL [ ; temporary function used just for the initialization... mime-type?: func[/local types type files][ unless find system/options 'mime-types [ - put system/options 'mime-types #[none] + put system/options 'mime-types #(none) ] types: any [system/options/mime-types make map! 110] parse [ diff --git a/src/mezz/codec-pdf.reb b/src/mezz/codec-pdf.reb index 2fdae89422..6cded37538 100644 --- a/src/mezz/codec-pdf.reb +++ b/src/mezz/codec-pdf.reb @@ -32,20 +32,20 @@ sec-pad: #{28BF4E5E4E758A4164004E56FFFA01082E2E00B6D0683E802F0CA9FE6453697A} ;- Rules rl_newline: [CRLF | LF | CR] -ch_number: #[bitset! #{000000000000FFC0}] ;charset "0123456789" -ch_delimiter: #[bitset! #{0000000004C1000A0000001400000014}] ;charset "()<>[]{}/%" -ch_str-valid: #[bitset! [not bits #{00EC000000C0000000000008}]] ;complement charset "^/^M^-^H^L()\" -ch_sp: #[bitset! #{0040000080}] ;charset " ^-" -ch_newline: #[bitset! #{0024}] ;charset CRLF -ch_spnl: #[bitset! #{0064000080}] ;charset " ^-^/^L^M" -ch_hex: #[bitset! #{000000000000FFC07FFFFFE07FFFFFE0}] ;charset [#"0" - #"9" #"a" - #"z" #"A" - #"Z"] -ch_hex-str: #[bitset! #{006400008000FFC07FFFFFE07FFFFFE0}] ;union union ch_hex sp ch_newline -ch_str: #[bitset! [not bits #{0000000000C0000000000008}]] ;complement charset "\()" -ch_str-esc: #[bitset! #{0000000000C0000000000008220228}] ;charset "nrtbf()\" -ch_not-hash: #[bitset! [not bits #{0000000010}]] ;complement charset "#" -ch_not-newline: #[bitset! [not bits #{0024}]] ;complement ch_newline -ch_not-delimiter: #[bitset! [not bits #{0000000004C1000A0000001400000014}]] ;complement ch_delimiter -ch_name: #[bitset! [not bits #{0064000084C1000A0000001400000014}]] ;complement union ch_delimiter ch_spnl +ch_number: #(bitset! #{000000000000FFC0}) ;charset "0123456789" +ch_delimiter: #(bitset! #{0000000004C1000A0000001400000014}) ;charset "()<>[]{}/%" +ch_str-valid: #(bitset! [not bits #{00EC000000C0000000000008}]) ;complement charset "^/^M^-^H^L()\" +ch_sp: #(bitset! #{0040000080}) ;charset " ^-" +ch_newline: #(bitset! #{0024}) ;charset CRLF +ch_spnl: #(bitset! #{0064000080}) ;charset " ^-^/^L^M" +ch_hex: #(bitset! #{000000000000FFC07FFFFFE07FFFFFE0}) ;charset [#"0" - #"9" #"a" - #"z" #"A" - #"Z"] +ch_hex-str: #(bitset! #{006400008000FFC07FFFFFE07FFFFFE0}) ;union union ch_hex sp ch_newline +ch_str: #(bitset! [not bits #{0000000000C0000000000008}]) ;complement charset "\()" +ch_str-esc: #(bitset! #{0000000000C0000000000008220228}) ;charset "nrtbf()\" +ch_not-hash: #(bitset! [not bits #{0000000010}]) ;complement charset "#" +ch_not-newline: #(bitset! [not bits #{0024}]) ;complement ch_newline +ch_not-delimiter: #(bitset! [not bits #{0000000004C1000A0000001400000014}]) ;complement ch_delimiter +ch_name: #(bitset! [not bits #{0064000084C1000A0000001400000014}]) ;complement union ch_delimiter ch_spnl rl_comment: [#"%" not #"%" copy value some ch_not-newline rl_newline] rl_boolean: ["true" (value: true) | "false" (value: false)] @@ -354,7 +354,7 @@ emit-string: func[val [any-string!]][ any [ s: some ch_str-valid e: (out: insert/part out s e) | 1 skip s: ( - out: insert out select #( + out: insert out select #[ #"^/" "\n" #"^M" "\r" #"^-" "\t" @@ -363,7 +363,7 @@ emit-string: func[val [any-string!]][ #"(" "\(" #")" "\)" #"\" "\\" - ) s/-1 + ] s/-1 ) ] ] @@ -425,7 +425,7 @@ get-xref-count: function[xrefs n][ emit-stream: func[obj [object!] /local data][ unless find obj 'spec [ - put obj 'spec #(Length: 0) + put obj 'spec #[Length: 0] ] data: any [obj/data #{}] unless any [ ; don't use compression @@ -532,7 +532,7 @@ register-codec [ version: none file-size: length? data trailer: none - objects: copy #() + objects: copy #[] referencies: copy [] startxref: none ] @@ -643,7 +643,7 @@ register-codec [ ] trailer: select pdf 'trailer unless trailer [ - put pdf 'trailer trailer: #(Info: #[none] Root: #[none]) + put pdf 'trailer trailer: #[Info: #(none) Root: #(none)] ] unless root: trailer/Root [ sys/log/debug 'PDF "Trying to locate `Catalog` in PDF objects." diff --git a/src/mezz/codec-safe.reb b/src/mezz/codec-safe.reb index 9c6444819d..6d4097d44f 100644 --- a/src/mezz/codec-safe.reb +++ b/src/mezz/codec-safe.reb @@ -164,7 +164,7 @@ sys/make-scheme [ ][ :value ] ] set: func[key [word!] val [any-type!]][put data :key :val] - rem: func[key][remove/key data :key #[unset!]] + rem: func[key][remove/key data :key #(unset!)] load: does [ date: modified? file data: system/codecs/safe/decode/key :file :pass diff --git a/src/mezz/mezz-banner.reb b/src/mezz/mezz-banner.reb index b0da8f9a70..11aa993ab5 100644 --- a/src/mezz/mezz-banner.reb +++ b/src/mezz/mezz-banner.reb @@ -55,7 +55,7 @@ sys/boot-banner: make-banner [ ["REBOL/" system/product #" " system/version " (Oldes branch)"] - = Copyright: "2012 REBOL Technologies" - = "" "2012-2023 Rebol Open Source Contributors" + = "" "2012-2024 Rebol Open Source Contributors" = "" "Apache 2.0 License, see LICENSE." = Website: "https://github.com/Oldes/Rebol3" - @@ -90,7 +90,8 @@ append sys/boot-banner * Direct access to TCP HTTP required (no proxies). * Use at your own risk. * ^[[1;32mTry/except^[[1;31m is deprecated and will be removed!^[[0m Use ^[[1;32mtry/with^[[0m instead. - + * This Rebol version has switched map and construction syntax! + See: https://github.com/Oldes/Rebol-issues/issues/2589 ^[[1;33mSpecial functions^[[0m: diff --git a/src/mezz/mezz-save.reb b/src/mezz/mezz-save.reb index 7a5f5cb136..bbe87bf419 100644 --- a/src/mezz/mezz-save.reb +++ b/src/mezz/mezz-save.reb @@ -87,7 +87,7 @@ save: function [ ] if length [ - append header-data [length: #[true]] ; any true? value will work + append header-data [length: #(true)] ; any true? value will work ] unless compress: true? find select header-data 'options 'compress [method: none] diff --git a/src/mezz/prot-http.reb b/src/mezz/prot-http.reb index b0330d3075..3c9ed80139 100644 --- a/src/mezz/prot-http.reb +++ b/src/mezz/prot-http.reb @@ -331,7 +331,7 @@ parse-write-dialect: func [port block /local spec][ ] ] -put system/catalog 'http-status-codes http-status-codes: #( +put system/catalog 'http-status-codes http-status-codes: #[ 200 "OK" 201 "Created" 202 "Accepted" @@ -384,7 +384,7 @@ put system/catalog 'http-status-codes http-status-codes: #( 508 "Loop Detected " 510 "Not Extended" 511 "Network Authentication Required" -) +] check-response: func [port /local conn res headers d1 d2 line info state awake spec date code][ state: port/state spec: port/spec @@ -543,7 +543,7 @@ do-redirect: func [port [port!] new-uri [url! string! file!] /local spec state h ] new-uri: construct/with new-uri port/scheme/spec new-uri/method: spec/method - new-uri/ref: as url! ajoin either find [#[none] 80 443] new-uri/port [ + new-uri/ref: as url! ajoin either find [#(none) 80 443] new-uri/port [ [new-uri/scheme "://" new-uri/host new-uri/path] ][ [new-uri/scheme "://" new-uri/host #":" new-uri/port new-uri/path]] diff --git a/src/mezz/prot-mail.reb b/src/mezz/prot-mail.reb index 0657fc6ac6..69f83c116e 100644 --- a/src/mezz/prot-mail.reb +++ b/src/mezz/prot-mail.reb @@ -208,7 +208,7 @@ get-id: func[base [integer!] /func n t][ counter: 0 ;- used when generating message ids ;; To make sure, that the latter case is correct (although it does not have to be)! -field-names: #( +field-names: #[ From: "From: " To: "To: " Cc: "Cc: " @@ -218,10 +218,10 @@ field-names: #( Organization: "Organization: " ;In-Reply-To: "In-Reply-To: " ;References: "References: " -) +] -atext: #[bitset! #{000000005F35FFC57FFFFFE3FFFFFFFE}] ;= charset [#"a"-#"z" #"A"-#"Z" #"0"-#"9" "!#$%&'*+-/=?^^_`{}|~"] -atext-sp: #[bitset! #{00400000DF35FFC57FFFFFE3FFFFFFFE}] ;= including sp and tab +atext: #(bitset! #{000000005F35FFC57FFFFFE3FFFFFFFE}) ;= charset [#"a"-#"z" #"A"-#"Z" #"0"-#"9" "!#$%&'*+-/=?^^_`{}|~"] +atext-sp: #(bitset! #{00400000DF35FFC57FFFFFE3FFFFFFFE}) ;= including sp and tab ;------------------------------------------------------------------ ;; This is for now just a placeholder, because only `write` action diff --git a/src/mezz/sys-load.reb b/src/mezz/sys-load.reb index 69c269e255..67d06ae93b 100644 --- a/src/mezz/sys-load.reb +++ b/src/mezz/sys-load.reb @@ -712,7 +712,7 @@ download-extension: function[ ] log/info 'REBOL ["Downloading:^[[m" url] ;; temporary turn off any logs - so/log: #[map! [http: 0 tls: 0]] + so/log: #(map! [http: 0 tls: 0]) bin: read url if %.gz = suffix? url [bin: decompress bin 'gzip] log/info 'REBOL ["Saving file:^[[m" file] diff --git a/src/mezz/sys-ports.reb b/src/mezz/sys-ports.reb index 8bb4ca53eb..16ca7fb7c4 100644 --- a/src/mezz/sys-ports.reb +++ b/src/mezz/sys-ports.reb @@ -102,15 +102,15 @@ url-parser: make object! [ ;-- URL Character Sets ;URIs include components and subcomponents that are delimited by characters in the "reserved" set. - gen-delims: #[bitset! #{000000001001002180000014}] ;= charset ":/?#[]@" - sub-delims: #[bitset! #{000000004BF80014}] ;= charset "!$&'()*+,;=" - reserved: #[bitset! #{000000005BF9003580000014}] ;= [gen-delims | sub-delims] + gen-delims: #(bitset! #{000000001001002180000014}) ;= charset ":/?#[]@" + sub-delims: #(bitset! #{000000004BF80014}) ;= charset "!$&'()*+,;=" + reserved: #(bitset! #{000000005BF9003580000014}) ;= [gen-delims | sub-delims] ;The purpose of reserved characters is to provide a set of delimiting ;characters that are distinguishable from other data within a URI. ;Characters that are allowed in a URI but do not have a reserved purpose are "unreserved" - unreserved: #[bitset! #{000000000006FFC07FFFFFE17FFFFFE2}] ;= compose [alpha | digit | (charset "-._~")] - scheme-char: #[bitset! #{000000000016FFC07FFFFFE07FFFFFE0}] ;= union alpha-num "+-." + unreserved: #(bitset! #{000000000006FFC07FFFFFE17FFFFFE2}) ;= compose [alpha | digit | (charset "-._~")] + scheme-char: #(bitset! #{000000000016FFC07FFFFFE07FFFFFE0}) ;= union alpha-num "+-." ;-- URL Grammar url-rules: [ diff --git a/src/modules/httpd.reb b/src/modules/httpd.reb index 9dec139d4c..583fa5c77d 100644 --- a/src/modules/httpd.reb +++ b/src/modules/httpd.reb @@ -37,7 +37,7 @@ Rebol [ 09-May-2023 "Oldes" {Root-less configuration possibility (default)} 14-Dec-2023 "Oldes" {Deprecated the `http-server` function in favor of `serve-http` with a different configuration input} ] - Needs: [3.11.0 mime-types] + Needs: [3.16.0 mime-types] ;; new construction syntax since 3.16.0 ] append system/options/log [httpd: 1] @@ -217,10 +217,10 @@ sys/make-scheme [ ] subport/extra/config: config: make map! [ - root: #[none] + root: #(none) index: [%index.html %index.htm] - keep-alive: #[true] - list-dir?: #[true] + keep-alive: #(true) + list-dir?: #(true) server-name: "Rebol3-HTTPd" ] ] @@ -618,7 +618,7 @@ sys/make-scheme [ ] Awake-Client: wrap [ - chars-method: #[bitset! #{00000000000000007FFFFFE0}] ; #"A" - #"Z" + chars-method: #(bitset! #{00000000000000007FFFFFE0}) ; #"A" - #"Z" ;from-method: ["GET" | "POST" | "HEAD" | "PUT" | "DELETE" | "TRACE" | "CONNECT" | "OPTIONS"] chars: complement union space: charset " " charset [#"^@" - #"^_"] CRLF2BIN: #{0D0A0D0A} diff --git a/src/modules/munge3.reb b/src/modules/munge3.reb index a2e8f6d871..6edb183b28 100644 --- a/src/modules/munge3.reb +++ b/src/modules/munge3.reb @@ -105,6 +105,7 @@ Rebol [ write-dsv Write block(s) of values to a delimited text file. write-excel Write block(s) of values to an Excel file. } + needs: 3.16.0 ;; new construction syntax ] @@ -298,7 +299,7 @@ ctx-munge: context [ remove-each row sort data [ any [ all [ - find ["" #[none]] row/1 + find ["" #(none)] row/1 1 = length? unique row ] either row = old-row [true] [old-row: row false] diff --git a/src/modules/spotify.reb b/src/modules/spotify.reb index c5f7b961c4..c78305f94b 100644 --- a/src/modules/spotify.reb +++ b/src/modules/spotify.reb @@ -14,7 +14,7 @@ Rebol [ https://developer.spotify.com/documentation/general/guides/authorization-guide/ https://aaronparecki.com/oauth-2-simplified/ } - Needs: 3.11.0 ;; using try/with instead of deprecated try/except + Needs: 3.16.0 ;; new construction syntax since 3.16.0 ] default-scopes: [ @@ -70,7 +70,7 @@ config: function[ ctx/client-secret: ask/hide "Client Secret: " ][ ;; when user hits ESC... sys/log/error 'spotify "Missing credentials!" - return #() + return #[] ] if empty? ctx/client-secret [ctx/client-secret: none] ;optional @@ -124,7 +124,7 @@ authorize: function [ unless string? client-id [ client-id: form client-id ] unless string? scopes: any [ctx/scopes default-scopes] [ scopes: form scopes ] - parse scopes [any [change some #[bitset! #{0064000080}] #"+" | skip]] ; url-encode spaces in scopes + parse scopes [any [change some #(bitset! #{0064000080}) #"+" | skip]] ; url-encode spaces in scopes unless integer? ctx/port [ ctx/port: 8989 ] ;@@ The value of redirect_uri here must exactly match one of the values @@ -285,7 +285,7 @@ request: func [ data [any-type!] /local ctx header result ][ - header: clear #() + header: clear #[] try/with [ ctx: config diff --git a/src/modules/unicode-utils.reb b/src/modules/unicode-utils.reb index 1a47ede153..b8df379302 100644 --- a/src/modules/unicode-utils.reb +++ b/src/modules/unicode-utils.reb @@ -42,7 +42,7 @@ decode-utf8: closure/with [ ] str ][ - utf8d: #[u8! [ + utf8d: make vector! [unsigned integer! 8 [ ;; The first part of the table maps bytes to character classes that ;; to reduce the size of the transition table and create bitmasks. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 @@ -61,7 +61,7 @@ decode-utf8: closure/with [ 12 12 12 12 12 12 12 24 12 12 12 12 12 24 12 12 12 12 12 12 12 24 12 12 12 12 12 12 12 12 12 36 12 36 12 12 12 36 12 12 12 12 12 36 12 36 12 12 12 36 12 12 12 12 12 12 12 12 12 12 - ]] + ] UTF8_ACCEPT: 0 UTF8_REJECT: 12 diff --git a/src/modules/webdriver.reb b/src/modules/webdriver.reb index b11979f6d7..9c77d1ab7b 100644 --- a/src/modules/webdriver.reb +++ b/src/modules/webdriver.reb @@ -12,7 +12,7 @@ Rebol [ 03-Jan-2024 "Oldes" {Initial version} ] Needs: [ - 3.11.0 ;; Minimal Rebol version required by WebScocket module + 3.16.0 ;; new map and construction syntax since 3.16.0 websocket json ] @@ -91,7 +91,7 @@ sys/make-scheme [ browser: none counter: 0 pending: 0 ;; increments when a new method is sent, decremented when response is received - req: #(id: 0 method: none params: #[none]) ;; used to send a command (to avoid cerating a new map) + req: #[id: 0 method: none params: #(none)] ;; used to send a command (to avoid cerating a new map) page-info: none ;; holds resolved info from an attached page page-conn: none ;; webscocket connection to an attached page ] diff --git a/src/os/win32/sys-codecs.cpp b/src/os/win32/sys-codecs.cpp index 815d17fefb..0d9920bcec 100644 --- a/src/os/win32/sys-codecs.cpp +++ b/src/os/win32/sys-codecs.cpp @@ -91,14 +91,23 @@ CODECS_API int DecodeImageFromFile(PCWSTR *uri, UINT frame, REBCDI *codi) // Global memory for stream will be released with the stream automaticaly HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, codi->len); if (!hMem) { - TRACE_ERR("GlobalAlloc"); hr = GetLastError(); - break; + ASSERT_HR("GlobalAlloc"); } hr = CreateStreamOnHGlobal(hMem, TRUE, &pStream); ASSERT_HR("CreateStreamOnHGlobal"); +#define use_memcpy +#ifdef use_memcpy + LPVOID tmp = GlobalLock(hMem); + if (!tmp) { + hr = GetLastError(); + ASSERT_HR("GlobalLock"); + } + memcpy(tmp, codi->data, codi->len); + GlobalUnlock(hMem); +#else ULONG written; hr = pStream->Write(codi->data, codi->len, &written); ASSERT_HR("pStream->Write"); @@ -106,7 +115,7 @@ CODECS_API int DecodeImageFromFile(PCWSTR *uri, UINT frame, REBCDI *codi) // WIC JPEG decoder needs the stream to seek to head manually! // https://stackoverflow.com/a/12928336/494472 pStream->Seek(zero, STREAM_SEEK_SET, NULL); - +#endif hr = pIWICFactory->CreateDecoderFromStream( pStream , NULL diff --git a/src/tests/test-extension-triangulate.r3 b/src/tests/test-extension-triangulate.r3 index 60e5932b9b..0cbaffba1c 100644 --- a/src/tests/test-extension-triangulate.r3 +++ b/src/tests/test-extension-triangulate.r3 @@ -5,27 +5,27 @@ Rebol [ import 'triangulate inp: object [ - points: #[f64! [ + points: #(f64! [ 0.0 0.0 10.0 0.0 10.0 10.0 0.0 10.0 2.5 2.5 - ]] - attributes: #[f64! [ + ]) + attributes: #(f64! [ 100.0 2.0 3.0 4.0 5.0 - ]] - markers: #[i64! [2 1 1 1 1]] - regions: #[f64! [ + ]) + markers: #(i64! [2 1 1 1 1]) + regions: #(f64! [ 5.0 5.0 10.0 ; Regional attribute (for whole mesh). 1.0 ; Area constraint that will not be used. - ]] + ]) report: true ] diff --git a/src/tests/test-httpd.r3 b/src/tests/test-httpd.r3 index 54ac51dae2..a395531acd 100644 --- a/src/tests/test-httpd.r3 +++ b/src/tests/test-httpd.r3 @@ -40,7 +40,7 @@ serve-http [ keep-alive: [30 100] ;= [timeout max-requests] or FALSE to turn it off log-access: %httpd-root/logs/test-access.log log-errors: %httpd-root/logs/test-errors.log - list-dir?: #[true] + list-dir?: #(true) ;- Server's actor functions actor: [ On-Accept: func [info [object!]][ diff --git a/src/tests/units/bincode-test.r3 b/src/tests/units/bincode-test.r3 index 05e27deb1d..227bfcda80 100644 --- a/src/tests/units/bincode-test.r3 +++ b/src/tests/units/bincode-test.r3 @@ -474,13 +474,13 @@ is-protected-error?: func[code][ --assert binary/read b #{0bad} --assert binary/read b #{Cafe} --assert tail? b/buffer - --assert [#[true] #[false] #[true]] = binary/read b [ + --assert [#(true) #(false) #(true)] = binary/read b [ ATz 0 ; reset position to head #{0bad} ; true and advance #{F00D} ; false, no advance #{Cafe} ; true and advance ] - --assert [#[true] #{CAFE}] = binary/read b [ATz 0 #{0bad} BYTES 2] + --assert [#(true) #{CAFE}] = binary/read b [ATz 0 #{0bad} BYTES 2] ===end-group=== diff --git a/src/tests/units/bitset-test.r3 b/src/tests/units/bitset-test.r3 index d569ab4bc3..4c13a632bf 100644 --- a/src/tests/units/bitset-test.r3 +++ b/src/tests/units/bitset-test.r3 @@ -1,4 +1,4 @@ -Rebol [ +Rebol [ Title: "Rebol3 bitset test script" Author: "Oldes, Peter W A Wood" File: %bitset-test.r3 @@ -53,26 +53,26 @@ --test-- "make bitset! from bitset!" ;@@ https://github.com/Oldes/Rebol-issues/issues/2420 - --assert #[bitset! #{}] = b1: charset "" - --assert #[bitset! #{}] = b2: make bitset! b1 + --assert #(bitset! #{}) = b1: charset "" + --assert #(bitset! #{}) = b2: make bitset! b1 b2/1: true - --assert #[bitset! #{}] = b1 - --assert #[bitset! #{40}] = b2 + --assert #(bitset! #{}) = b1 + --assert #(bitset! #{40}) = b2 --test-- "charset" ;@@ https://github.com/Oldes/Rebol-issues/issues/1092 - --assert #[bitset! #{80}] = charset #"^@" - --assert #[bitset! #{8000}] = charset/length #"^@" 16 + --assert #(bitset! #{80}) = charset #"^@" + --assert #(bitset! #{8000}) = charset/length #"^@" 16 --test-- "make bitset! from block" ;@@ https://github.com/Oldes/Rebol-issues/issues/1335 - --assert #[bitset! #{6000}] = make bitset! [#{0102}] - --assert #[bitset! #{60}] = make bitset! [1 2] - --assert #[bitset! #{700000}] = make bitset! [#{010203}] - --assert #[bitset! #{00008000800080}] = make bitset! [#{102030}] - --assert #[bitset! #{7C00800080008000}] = make bitset! [#{0102030405102030}] + --assert #(bitset! #{6000}) = make bitset! [#{0102}] + --assert #(bitset! #{60}) = make bitset! [1 2] + --assert #(bitset! #{700000}) = make bitset! [#{010203}] + --assert #(bitset! #{00008000800080}) = make bitset! [#{102030}] + --assert #(bitset! #{7C00800080008000}) = make bitset! [#{0102030405102030}] ;@@ https://github.com/Oldes/Rebol-issues/issues/1226 - --assert #[bitset! #{FFFE}] = make bitset! [#"^(00)" - #"^(0E)"] + --assert #(bitset! #{FFFE}) = make bitset! [#"^(00)" - #"^(0E)"] ===end-group=== @@ -180,7 +180,7 @@ ===start-group=== "modify" --test-- "alter" ;@@ https://github.com/Oldes/Rebol-issues/issues/422 - bs: #[bitset! #{00}] + bs: #(bitset! #{00}) --assert true = alter bs 1 --assert #{40} = to binary! bs --assert false = alter bs 1 @@ -369,7 +369,7 @@ ;@@ https://github.com/Oldes/Rebol-issues/issues/1541 b: charset " " b/48: true - --assert b = #[bitset! #{00000000800080}] + --assert b = #(bitset! #{00000000800080}) b: complement charset " " b/48: none --assert b = make bitset! [not bits #{00000000800080}] diff --git a/src/tests/units/codecs-test-pdf.r3 b/src/tests/units/codecs-test-pdf.r3 index 05f954641b..415bb907b4 100644 --- a/src/tests/units/codecs-test-pdf.r3 +++ b/src/tests/units/codecs-test-pdf.r3 @@ -29,45 +29,45 @@ if find codecs 'pdf [ --test-- "Minimal PDF file" empty-pdf: object [ - trailer: #( + trailer: #[ Info: 1x0 Root: 2x0 - ) - objects: #( + ] + objects: #[ ;- Document Information Dictionary - 1x0 #( + 1x0 #[ Producer: "Rebol" - ) + ] ;- Document Catalog - 2x0 #( + 2x0 #[ Type: Catalog Pages: 3x0 - ) + ] ;- Root of the document's page tree - 3x0 #( + 3x0 #[ Type: Pages Kids: [5x0] Count: 1 - ) + ] ;- Procedure Sets 4x0 [ PDF ; Painting and graphics state ] ;- First page - 5x0 #( + 5x0 #[ Type: Page Parent: 3x0 MediaBox: [0 0 612 792] Contents: 6x0 - Resources: #( + Resources: #[ ProcSet: 4x0 - ) - ) + ] + ] ;- Empty content - 6x0 #[object! [ + 6x0 #(object! [ data: "" - ]] - ) + ]) + ] ] --assert not error? try [save %tmp-empty.pdf empty-pdf] --assert object? try [p2: load %tmp-empty.pdf] @@ -79,14 +79,14 @@ if find codecs 'pdf [ ; include text processing.. append pdf/objects/4x0 'Text ; include font - put pdf/objects 7x0 #( + put pdf/objects 7x0 #[ Type: Font Subtype: Type1 Name: F1 BaseFont: Helvetica Encoding: MacRomanEncoding - ) - pdf/objects/5x0/Resources/Font: #(F1: 7x0) + ] + pdf/objects/5x0/Resources/Font: #[F1: 7x0] ; make some content pdf/objects/6x0/Data: { BT diff --git a/src/tests/units/codecs-test.r3 b/src/tests/units/codecs-test.r3 index 1384959acb..57b414641e 100644 --- a/src/tests/units/codecs-test.r3 +++ b/src/tests/units/codecs-test.r3 @@ -175,7 +175,7 @@ if find codecs 'wav [ bin: none --test-- "Encode WAV" - samples: #[i16! [0 -1000 -2000 -1000 0 1000 2000 1000 0]] + samples: #(i16! [0 -1000 -2000 -1000 0 1000 2000 1000 0]) --assert binary? bin: encode 'wav :samples --assert object? snd: decode 'wav :bin --assert 'wave = snd/type @@ -430,7 +430,7 @@ try [import 'json] if find codecs 'JSON [ ===start-group=== "JSON codec" --test-- "JSON encode/decode" - data: #(a: 1 b: #(c: 2.0) d: "^/^-") + data: #[a: 1 b: #[c: 2.0] d: "^/^-"] str: encode 'JSON data --assert data = decode 'JSON str ; Github is using "+1" and "-1" keys in the `reactions` data now @@ -791,7 +791,7 @@ if find codecs 'safe [ ===start-group=== "SAFE codec" --test-- "Save/Load SAFE file" foreach data [ - #(key: "Hello") + #[key: "Hello"] 43 #{DEADBEEF} [key: "aaa" value: 12] @@ -812,7 +812,7 @@ if find codecs 'safe [ --assert none? system/user/name --assert not error? try [set-user/p temp-user "passw"] --assert "hello" = user's key ;; resolve the data - --assert not error? try [su #[none]] ;; release user using none value + --assert not error? try [su #(none)] ;; release user using none value --assert none? system/user/name try [delete system/user/data/spec/ref] diff --git a/src/tests/units/conditional-test.r3 b/src/tests/units/conditional-test.r3 index c4eea916ac..0ea58b01f2 100644 --- a/src/tests/units/conditional-test.r3 +++ b/src/tests/units/conditional-test.r3 @@ -138,9 +138,9 @@ Rebol [ sb10-i: true sb10-j: "REBOL" switch sb10-i [ - #[false] [sb10-j: "Earl"] - #[true] [sb10-j: "Red"] - #[true] [sb10-j: "Peter"] + #(false) [sb10-j: "Earl"] + #(true) [sb10-j: "Red"] + #(true) [sb10-j: "Peter"] ] --assert sb10-j = "Red" @@ -180,8 +180,8 @@ Rebol [ switch sb15-i [ 1 [sb15-j: "Earl"] integer! [sb15-j: "Peter"] - #[integer!] [sb15-j: "Red"] - #[char!] [sb15-j: "Blue"] + #(integer!) [sb15-j: "Red"] + #(char!) [sb15-j: "Blue"] ] --assert sb15-j = "Red" diff --git a/src/tests/units/copy-test.r3 b/src/tests/units/copy-test.r3 index 86a2e941c7..ed554f8931 100644 --- a/src/tests/units/copy-test.r3 +++ b/src/tests/units/copy-test.r3 @@ -25,11 +25,11 @@ copyable-data: make object! [ set-path: quote a/b: get-path: quote :a/b lit-path: quote 'a/b - map: #(a: 1) - object: #[object! [a: 1]] - image: #[image! 1x1 #{FFFFFF}] - bitset: #[bitset! #{FF}] - vector: #[u32! 3] + map: #[a: 1] + object: #(object! [a: 1]) + image: #(image! 1x1 #{FFFFFF}) + bitset: #(bitset! #{FF}) + vector: #(u32! 3) error: try [1 / 0] ;TODO: struct, ] @@ -42,14 +42,14 @@ not-copyable-data: make object! [ tuple: 1.1.1 date: 1-1-2000 time: 1:1:1 - logic: #[true] - none: #[none] - gob: #[gob![size: 20x20]] + logic: #(true) + none: #(none) + gob: #(gob![size: 20x20]) word: 'foo lit-word: quote 'foo set-word: quote foo: get-word: quote :foo - typeset: #[typeset! [integer! percent!]] + typeset: #(typeset! [integer! percent!]) module: system/modules/help ;@@ or should it be copyable? event: make event! [] ;@@ or should it be copyable? ;handle @@ -95,12 +95,12 @@ not-copyable-data: make object! [ ===start-group=== "Copy map!" --test-- "copy/deep map!" - m1: #() - m1/b: copy [1 2 s: "" u: http://foo b: [3 4] o: #[object! []]] + m1: #[] + m1/b: copy [1 2 s: "" u: http://foo b: [3 4] o: #(object! [])] m1/s: copy "" m1/u: http:// - m1/o: #[object! [ s: "" o: #[object![]] ]] - m1/m: #(s: "" u: http://foo b: [3 4] o: #[object! []]) + m1/o: #(object! [ s: "" o: #(object![]) ]) + m1/m: #[s: "" u: http://foo b: [3 4] o: #(object! [])] m2: copy/deep m1 --assert not same? m1/b m2/b --assert not same? m1/s m2/s @@ -153,7 +153,7 @@ not-copyable-data: make object! [ --assert not same? m1/o/o m5/o/o ; because /deep is used --test-- "copy/deep/types map! (only maps and strings)" - m6: copy/deep/types m1 #[typeset! [string! map!]] + m6: copy/deep/types m1 #(typeset! [string! map!]) --assert same? m1/b m6/b --assert not same? m1/s m6/s --assert same? m1/u m6/u @@ -165,7 +165,7 @@ not-copyable-data: make object! [ --assert same? m1/m/o m6/m/o --test-- "copy/deep/types map! (only maps and strings)" - m7: copy/deep/types m1 #[typeset! [string! map!]] + m7: copy/deep/types m1 #(typeset! [string! map!]) --assert same? m1/b m7/b --assert not same? m1/s m7/s --assert same? m1/u m7/u @@ -199,11 +199,11 @@ not-copyable-data: make object! [ ===start-group=== "Copy object!" --test-- "copy/deep object!" o1: make object! [ - b: copy [1 2 s: "" u: http://foo b: [3 4] o: #[object! []]] + b: copy [1 2 s: "" u: http://foo b: [3 4] o: #(object! [])] s: copy "" u: http:// - o: #[object! [ s: "" u: http://foo b: [3 4] o: #[object![]] ]] - m: #(s: "" u: http://foo b: [3 4] o: #[object! []]) + o: #(object! [ s: "" u: http://foo b: [3 4] o: #(object![]) ]) + m: #[s: "" u: http://foo b: [3 4] o: #(object! [])] ] o2: copy/deep o1 --assert not same? o1/b o2/b @@ -253,7 +253,7 @@ not-copyable-data: make object! [ --assert not same? o1/o/o o5/o/o ; because /deep is used --test-- "copy/deep/types object! (only maps and strings)" - o6: copy/deep/types o1 #[typeset! [string! map!]] + o6: copy/deep/types o1 #(typeset! [string! map!]) --assert same? o1/b o6/b --assert not same? o1/s o6/s --assert same? o1/u o6/u @@ -265,7 +265,7 @@ not-copyable-data: make object! [ --assert same? o1/m/o o6/m/o --test-- "copy/deep/types object! (only objects and strings)" - o7: copy/deep/types o1 #[typeset! [string! object!]] + o7: copy/deep/types o1 #(typeset! [string! object!]) --assert same? o1/b o7/b --assert not same? o1/s o7/s --assert same? o1/u o7/u @@ -299,11 +299,11 @@ not-copyable-data: make object! [ ===start-group=== "Copy block!" --test-- "copy/deep block!" b1: reduce [ - quote b: copy [1 2 s: "" u: http://foo b: [3 4] o: #[object! []]] + quote b: copy [1 2 s: "" u: http://foo b: [3 4] o: #(object! [])] quote s: copy "" quote u: http:// - quote o: #[object! [ s: "" u: http:// b: [] o: #[object![]] ]] - quote m: #(s: "" u: http://foo b: [3 4] o: #[object! []]) + quote o: #(object! [ s: "" u: http:// b: [] o: #(object![]) ]) + quote m: #[s: "" u: http://foo b: [3 4] o: #(object! [])] ] b2: copy/deep b1 --assert not same? b1/b b2/b @@ -371,7 +371,7 @@ not-copyable-data: make object! [ --assert not same? b1/o/o b5/o/o ; because /deep is used --test-- "copy/deep/types block! (only block and strings)" - b6: copy/deep/types b1 #[typeset! [block! string!]] + b6: copy/deep/types b1 #(typeset! [block! string!]) --assert not same? b1/b b6/b --assert not same? b1/s b6/s --assert same? b1/u b6/u @@ -383,7 +383,7 @@ not-copyable-data: make object! [ --assert same? b1/b/o b6/b/o --test-- "copy/deep/types block! (only objects, blocks and strings)" - b7: copy/deep/types b1 #[typeset! [string! block! object!]] + b7: copy/deep/types b1 #(typeset! [string! block! object!]) --assert not same? b1/b b7/b --assert not same? b1/s b7/s --assert same? b1/u b7/u diff --git a/src/tests/units/crash-test.r3 b/src/tests/units/crash-test.r3 index 387f2d7284..953c5460a0 100644 --- a/src/tests/units/crash-test.r3 +++ b/src/tests/units/crash-test.r3 @@ -137,9 +137,9 @@ Rebol [ m: [a 1] --assert error? try [m/a:] ---test-- {#[map! 0]} +--test-- {#(map! 0)} ;@@ https://github.com/Oldes/Rebol-issues/issues/940 - --assert error? try [load {#[map! 0]}] ;- no crash + --assert error? try [load {#(map! 0)}] ;- no crash --test-- {reduce reduce [:self]} ;@@ https://github.com/Oldes/Rebol-issues/issues/1756 diff --git a/src/tests/units/crypt-port-ccm-test.r3 b/src/tests/units/crypt-port-ccm-test.r3 index eff154acec..76e9f56386 100644 --- a/src/tests/units/crypt-port-ccm-test.r3 +++ b/src/tests/units/crypt-port-ccm-test.r3 @@ -1675,7 +1675,7 @@ decrypt-tests: [ #{9a04c241} #{3796cf51b87266} #{} - 4 #[none] + 4 #(none) #{4bb3c4a4f893ad8c9bdc833c325d62b3} #{75d582db43ce9b13ab4b6f7f14341330} @@ -1687,7 +1687,7 @@ decrypt-tests: [ #{3a65e03af37b81d05acc7ec1bc39deb0} #{3796cf51b87266} #{} - 16 #[none] + 16 #(none) #{4bb3c4a4f893ad8c9bdc833c325d62b3} #{90156f3f} @@ -1699,7 +1699,7 @@ decrypt-tests: [ #{88909016} #{a16a2e741f1cd9717285b6d882} #{} - 4 #[none] + 4 #(none) #{19ebfde2d5468ba0a3031bde629b11fd} #{fb04dc5a44c6bb000f2440f5154364b4} @@ -1711,7 +1711,7 @@ decrypt-tests: [ #{5447075bf42a59b91f08064738b015ab} #{a16a2e741f1cd9717285b6d882} #{} - 16 #[none] + 16 #(none) #{19ebfde2d5468ba0a3031bde629b11fd} #{a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b} @@ -1723,7 +1723,7 @@ decrypt-tests: [ #{50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c} #{31f8fa25827d48} #{} - 4 #[none] + 4 #(none) #{197afb02ffbd8f699dacae87094d5243} #{24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e} @@ -1735,7 +1735,7 @@ decrypt-tests: [ #{7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4} #{31f8fa25827d48} #{} - 16 #[none] + 16 #(none) #{197afb02ffbd8f699dacae87094d5243} #{4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9} @@ -1747,7 +1747,7 @@ decrypt-tests: [ #{118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9} #{49004912fdd7269279b1f06a89} #{} - 4 #[none] + 4 #(none) #{90929a4b0ac65b350ad1591611fe4829} #{4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a} @@ -1759,7 +1759,7 @@ decrypt-tests: [ #{0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337} #{49004912fdd7269279b1f06a89} #{} - 16 #[none] + 16 #(none) #{90929a4b0ac65b350ad1591611fe4829} #{782e4318} @@ -1771,7 +1771,7 @@ decrypt-tests: [ #{a04f270a} #{a265480ca88d5f} #{a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe} - 4 #[none] + 4 #(none) #{6a798d7c5e1a72b43e20ad5c7b08567b} #{41b476013f45e4a781f253a6f3b1e530} @@ -1783,7 +1783,7 @@ decrypt-tests: [ #{f9f018fcd125822616083fffebc4c8e6} #{a265480ca88d5f} #{a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe} - 16 #[none] + 16 #(none) #{6a798d7c5e1a72b43e20ad5c7b08567b} #{9f69f24f} @@ -1795,7 +1795,7 @@ decrypt-tests: [ #{e17afaa4} #{8739b4bea1a099fe547499cbc6} #{f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7} - 4 #[none] + 4 #(none) #{f9fdca4ac64fe7f014de0f43039c7571} #{1859ac36a40a6b28b34266253627797a} @@ -1807,7 +1807,7 @@ decrypt-tests: [ #{edf8b46eb69ac0044116019dec183072} #{8739b4bea1a099fe547499cbc6} #{f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7} - 16 #[none] + 16 #(none) #{f9fdca4ac64fe7f014de0f43039c7571} #{6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa} @@ -1819,7 +1819,7 @@ decrypt-tests: [ #{4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69} #{fdd2d6f503c915} #{5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e} - 4 #[none] + 4 #(none) #{a7aa635ea51b0bb20a092bd5573e728c} #{b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f} @@ -1831,7 +1831,7 @@ decrypt-tests: [ #{df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b} #{fdd2d6f503c915} #{5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e} - 16 #[none] + 16 #(none) #{a7aa635ea51b0bb20a092bd5573e728c} #{934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329} @@ -1843,7 +1843,7 @@ decrypt-tests: [ #{f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee} #{0812757ad0cc4d17c4cfe7a642} #{ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10} - 4 #[none] + 4 #(none) #{26511fb51fcfa75cb4b44da75a6e5a0e} #{50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503} @@ -1855,7 +1855,7 @@ decrypt-tests: [ #{78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306} #{0812757ad0cc4d17c4cfe7a642} #{ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10} - 16 #[none] + 16 #(none) ] DVPT AES-192-CCM "CCM auth decrypt tag NIST DVPT AES-192" @@ -1870,7 +1870,7 @@ decrypt-tests: [ #{80745de9} #{3796cf51b87266} #{} - 4 #[none] + 4 #(none) #{4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65} #{17223038fa99d53681ca1beabe78d1b4} @@ -1882,7 +1882,7 @@ decrypt-tests: [ #{d0e1eeef4d2a264536bb1c2c1bde7c35} #{3796cf51b87266} #{} - 16 #[none] + 16 #(none) #{4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65} #{fe69ed84} @@ -1894,7 +1894,7 @@ decrypt-tests: [ #{db7ffc82} #{a16a2e741f1cd9717285b6d882} #{} - 4 #[none] + 4 #(none) #{19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa} #{0c66a8e547ed4f8c2c9a9a1eb5d455b9} @@ -1906,7 +1906,7 @@ decrypt-tests: [ #{38757b3a61a4dc97ca3ab88bf1240695} #{a16a2e741f1cd9717285b6d882} #{} - 16 #[none] + 16 #(none) #{19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa} #{411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54} @@ -1918,7 +1918,7 @@ decrypt-tests: [ #{32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036} #{31f8fa25827d48} #{} - 4 #[none] + 4 #(none) #{197afb02ffbd8f699dacae87094d524324576b99844f75e1} #{cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20} @@ -1930,7 +1930,7 @@ decrypt-tests: [ #{ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d} #{31f8fa25827d48} #{} - 16 #[none] + 16 #(none) #{197afb02ffbd8f699dacae87094d524324576b99844f75e1} #{042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277} @@ -1942,7 +1942,7 @@ decrypt-tests: [ #{1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775} #{49004912fdd7269279b1f06a89} #{} - 4 #[none] + 4 #(none) #{90929a4b0ac65b350ad1591611fe48297e03956f6083e451} #{a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a} @@ -1954,7 +1954,7 @@ decrypt-tests: [ #{9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445} #{49004912fdd7269279b1f06a89} #{} - 16 #[none] + 16 #(none) #{90929a4b0ac65b350ad1591611fe48297e03956f6083e451} #{1d089a5f} @@ -1966,7 +1966,7 @@ decrypt-tests: [ #{2f46022a} #{a265480ca88d5f} #{a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe} - 4 #[none] + 4 #(none) #{6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2} #{5280a2137fee3deefcfe9b63a1199fb3} @@ -1978,7 +1978,7 @@ decrypt-tests: [ #{d40a7318c5f2d82f838c0beeefe0d598} #{a265480ca88d5f} #{a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe} - 16 #[none] + 16 #(none) #{6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2} #{5e0eaebd} @@ -1990,7 +1990,7 @@ decrypt-tests: [ #{71b7fc33} #{8739b4bea1a099fe547499cbc6} #{f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7} - 4 #[none] + 4 #(none) #{f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4} #{d07ccf9fdc3d33aa94cda3d230da707c} @@ -2002,7 +2002,7 @@ decrypt-tests: [ #{65fe32b649dc328c9f531584897e85b3} #{8739b4bea1a099fe547499cbc6} #{f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7} - 16 #[none] + 16 #(none) #{f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4} #{9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1} @@ -2014,7 +2014,7 @@ decrypt-tests: [ #{84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825} #{fdd2d6f503c915} #{5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e} - 4 #[none] + 4 #(none) #{a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d} #{6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975} @@ -2026,7 +2026,7 @@ decrypt-tests: [ #{4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3} #{fdd2d6f503c915} #{5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e} - 16 #[none] + 16 #(none) #{a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d} #{16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce} @@ -2038,7 +2038,7 @@ decrypt-tests: [ #{df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e} #{0812757ad0cc4d17c4cfe7a642} #{ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10} - 4 #[none] + 4 #(none) #{26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886} #{c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8} @@ -2050,7 +2050,7 @@ decrypt-tests: [ #{d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388} #{0812757ad0cc4d17c4cfe7a642} #{ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10} - 16 #[none] + 16 #(none) ] DVPT AES-256-CCM "CCM auth decrypt tag NIST DVPT AES-256" @@ -2065,7 +2065,7 @@ decrypt-tests: [ #{46a908ed} #{d3d5424e20fbec} #{} - 4 #[none] + 4 #(none) #{e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8} #{8207eb14d33855a52acceed17dbcbf6e} @@ -2077,7 +2077,7 @@ decrypt-tests: [ #{60f8e127cb4d30db6df0622158cd931d} #{d3d5424e20fbec} #{} - 16 #[none] + 16 #(none) #{e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8} #{8a19a133} @@ -2089,7 +2089,7 @@ decrypt-tests: [ #{2e317f1b} #{3c0e2815d37d844f7ac240ba9d} #{} - 4 #[none] + 4 #(none) #{af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569} #{97e1a8dd4259ccd2e431e057b0397fcf} @@ -2101,7 +2101,7 @@ decrypt-tests: [ #{5a9596c511ea6a8671adefc4f2157d8b} #{3c0e2815d37d844f7ac240ba9d} #{} - 16 #[none] + 16 #(none) #{af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569} #{64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59} @@ -2113,7 +2113,7 @@ decrypt-tests: [ #{c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75} #{bfcda8b5a2d0d2} #{} - 4 #[none] + 4 #(none) #{f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453} #{bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305} @@ -2125,7 +2125,7 @@ decrypt-tests: [ #{afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f} #{bfcda8b5a2d0d2} #{} - 16 #[none] + 16 #(none) #{f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453} #{63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f} @@ -2137,7 +2137,7 @@ decrypt-tests: [ #{bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099} #{894dcaa61008eb8fb052c60d41} #{} - 4 #[none] + 4 #(none) #{1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4} #{f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3} @@ -2149,7 +2149,7 @@ decrypt-tests: [ #{c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc} #{894dcaa61008eb8fb052c60d41} #{} - 16 #[none] + 16 #(none) #{1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4} #{92d00fbe} @@ -2161,7 +2161,7 @@ decrypt-tests: [ #{9143e5c4} #{78c46e3249ca28} #{232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc} - 4 #[none] + 4 #(none) #{a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088} #{93af11a08379eb37a16aa2837f09d69d} @@ -2173,7 +2173,7 @@ decrypt-tests: [ #{d19b0c14ec686a7961ca7c386d125a65} #{78c46e3249ca28} #{232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc} - 16 #[none] + 16 #(none) #{a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088} #{866d4227} @@ -2185,7 +2185,7 @@ decrypt-tests: [ #{94cb1127} #{e8de970f6ee8e80ede933581b5} #{89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a} - 4 #[none] + 4 #(none) #{8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a} #{867b0d87cf6e0f718200a97b4f6d5ad5} @@ -2197,7 +2197,7 @@ decrypt-tests: [ #{677a040d46ee3f2b7838273bdad14f16} #{e8de970f6ee8e80ede933581b5} #{89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a} - 16 #[none] + 16 #(none) #{8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a} #{c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720} @@ -2209,7 +2209,7 @@ decrypt-tests: [ #{94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9} #{6ba004fd176791} #{5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b} - 4 #[none] + 4 #(none) #{705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe} #{3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a} @@ -2221,7 +2221,7 @@ decrypt-tests: [ #{d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9} #{6ba004fd176791} #{5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b} - 16 #[none] + 16 #(none) #{705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe} #{c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339} @@ -2233,7 +2233,7 @@ decrypt-tests: [ #{60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623} #{8fa501c5dd9ac9b868144c9fa5} #{5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800} - 4 #[none] + 4 #(none) #{314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e} #{8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203} @@ -2245,7 +2245,7 @@ decrypt-tests: [ #{516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16} #{8fa501c5dd9ac9b868144c9fa5} #{5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800} - 16 #[none] + 16 #(none) ] ] diff --git a/src/tests/units/crypt-port-test.r3 b/src/tests/units/crypt-port-test.r3 index 48a8abdd15..9ed46c0067 100644 --- a/src/tests/units/crypt-port-test.r3 +++ b/src/tests/units/crypt-port-test.r3 @@ -22,34 +22,34 @@ test-crypt: func[port key iv plain cipher][ tests: [ AES-128-ECB [ #{000102030405060708090A0B0C0D0E0F} - #[none] + #(none) #{00112233445566778899AABBCCDDEEFF} #{69C4E0D86A7B0430D8CDB78070B4C55A} ;NIST document SP800-38A - #{2B7E151628AED2A6ABF7158809CF4F3C} #[none] #{6BC1BEE22E409F96E93D7E117393172A} #{3AD77BB40D7A3660A89ECAF32466EF97} - #{2B7E151628AED2A6ABF7158809CF4F3C} #[none] #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{F5D3D58503B9699DE785895A96FDBAAF} - #{2B7E151628AED2A6ABF7158809CF4F3C} #[none] #{30C81C46A35CE411E5FBC1191A0A52EF} #{43B1CD7F598ECE23881B00E3ED030688} - #{2B7E151628AED2A6ABF7158809CF4F3C} #[none] #{F69F2445DF4F9B17AD2B417BE66C3710} #{7B0C785E27E8AD3F8223207104725DD4} + #{2B7E151628AED2A6ABF7158809CF4F3C} #(none) #{6BC1BEE22E409F96E93D7E117393172A} #{3AD77BB40D7A3660A89ECAF32466EF97} + #{2B7E151628AED2A6ABF7158809CF4F3C} #(none) #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{F5D3D58503B9699DE785895A96FDBAAF} + #{2B7E151628AED2A6ABF7158809CF4F3C} #(none) #{30C81C46A35CE411E5FBC1191A0A52EF} #{43B1CD7F598ECE23881B00E3ED030688} + #{2B7E151628AED2A6ABF7158809CF4F3C} #(none) #{F69F2445DF4F9B17AD2B417BE66C3710} #{7B0C785E27E8AD3F8223207104725DD4} ] AES-192-ECB [ #{000102030405060708090A0B0C0D0E0F1011121314151617} - #[none] + #(none) #{00112233445566778899AABBCCDDEEFF} #{DDA97CA4864CDFE06EAF70A0EC0D7191} - #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #[none] #{6BC1BEE22E409F96E93D7E117393172A} #{BD334F1D6E45F25FF712A214571FA5CC} - #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #[none] #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{974104846D0AD3AD7734ECB3ECEE4EEF} - #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #[none] #{30C81C46A35CE411E5FBC1191A0A52EF} #{EF7AFD2270E2E60ADCE0BA2FACE6444E} - #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #[none] #{F69F2445DF4F9B17AD2B417BE66C3710} #{9A4B41BA738D6C72FB16691603C18E0E} + #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #(none) #{6BC1BEE22E409F96E93D7E117393172A} #{BD334F1D6E45F25FF712A214571FA5CC} + #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #(none) #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{974104846D0AD3AD7734ECB3ECEE4EEF} + #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #(none) #{30C81C46A35CE411E5FBC1191A0A52EF} #{EF7AFD2270E2E60ADCE0BA2FACE6444E} + #{8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B} #(none) #{F69F2445DF4F9B17AD2B417BE66C3710} #{9A4B41BA738D6C72FB16691603C18E0E} ] AES-256-ECB [ - #{000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F} #[none] #{00112233445566778899AABBCCDDEEFF} #{8EA2B7CA516745BFEAFC49904B496089} + #{000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F} #(none) #{00112233445566778899AABBCCDDEEFF} #{8EA2B7CA516745BFEAFC49904B496089} - #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #[none] #{6BC1BEE22E409F96E93D7E117393172A} #{F3EED1BDB5D2A03C064B5A7E3DB181F8} - #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #[none] #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{591CCB10D410ED26DC5BA74A31362870} - #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #[none] #{30C81C46A35CE411E5FBC1191A0A52EF} #{B6ED21B99CA6F4F9F153E7B1BEAFED1D} - #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #[none] #{F69F2445DF4F9B17AD2B417BE66C3710} #{23304B7A39F9F3FF067D8D8F9E24ECC7} + #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #(none) #{6BC1BEE22E409F96E93D7E117393172A} #{F3EED1BDB5D2A03C064B5A7E3DB181F8} + #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #(none) #{AE2D8A571E03AC9C9EB76FAC45AF8E51} #{591CCB10D410ED26DC5BA74A31362870} + #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #(none) #{30C81C46A35CE411E5FBC1191A0A52EF} #{B6ED21B99CA6F4F9F153E7B1BEAFED1D} + #{603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4} #(none) #{F69F2445DF4F9B17AD2B417BE66C3710} #{23304B7A39F9F3FF067D8D8F9E24ECC7} ] AES-128-CBC [ #{2B7E151628AED2A6ABF7158809CF4F3C} #{000102030405060708090A0B0C0D0E0F} #{6BC1BEE22E409F96E93D7E117393172A} #{7649ABAC8119B246CEE98E9B12E9197D} @@ -193,24 +193,24 @@ monte-carlo-test-crypt: function[port key iv plain cipher][ monte-carlo-ecb-tests: [ AES-128-ECB [ #{00000000000000000000000000000000} - #[none] + #(none) #{00000000000000000000000000000000} #{C34C052CC0DA8D73451AFE5F03BE297F} #{00000000000000000000000000000000} - #[none] + #(none) #{44416AC2D1F53C583303917E6BE9EBE0} #{00000000000000000000000000000000} ] AES-192-ECB [ #{000000000000000000000000000000000000000000000000} - #[none] + #(none) #{48E31E9E256718F29229319C19F15BA4} #{00000000000000000000000000000000} ] AES-256-ECB [ #{0000000000000000000000000000000000000000000000000000000000000000} - #[none] + #(none) #{058CCFFDBBCB382D1F6F56585D8A4ADE} #{00000000000000000000000000000000} ] diff --git a/src/tests/units/crypt-test.r3 b/src/tests/units/crypt-test.r3 index 0392f0509a..5f635b1b66 100644 --- a/src/tests/units/crypt-test.r3 +++ b/src/tests/units/crypt-test.r3 @@ -155,7 +155,7 @@ YYFw8pfGesIFoEuVth4HKyF8k1y4mRUnYHP1XNMNMJl1JcEArC2asV8sHf6zSPVffozZ --assert block? Load-PKIX pkix --assert binary? Load-PKIX/binary pkix - --assert "#[handle! rsa]" = mold key: decode 'ssh-key pkix + --assert "#(handle! rsa)" = mold key: decode 'ssh-key pkix release key ; don't wait on GC, release it now --test-- "SSH-public-key-2" diff --git a/src/tests/units/datatype-test.r3 b/src/tests/units/datatype-test.r3 index 67233a0e2d..0ac3206852 100644 --- a/src/tests/units/datatype-test.r3 +++ b/src/tests/units/datatype-test.r3 @@ -12,7 +12,7 @@ Rebol [ --test-- "system/catalog/datatypes" --assert block? system/catalog/datatypes --assert datatype? first system/catalog/datatypes - --assert #[end!] = first system/catalog/datatypes + --assert #(end!) = first system/catalog/datatypes --test-- "reflect datatype!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1534 @@ -30,12 +30,12 @@ Rebol [ --test-- "find datatype!" ;@@ https://github.com/Oldes/Rebol-issues/issues/256 --assert none? find reduce [string! binary!] binary! - --assert none? find [#[string!] #[binary!]] #[binary!] - --assert none? find [#[string!] #[binary!]] binary! + --assert none? find [#(string!) #(binary!)] #(binary!) + --assert none? find [#(string!) #(binary!)] binary! --assert not none? find/only reduce [string! binary!] binary! - --assert not none? find/only [#[string!] #[binary!]] #[binary!] - --assert not none? find/only [#[string!] #[binary!]] binary! + --assert not none? find/only [#(string!) #(binary!)] #(binary!) + --assert not none? find/only [#(string!) #(binary!)] binary! --assert not none? find ["test"] string! --assert not none? find ["test"] series! @@ -43,8 +43,8 @@ Rebol [ --assert ["aha"] = find reduce [integer! "aha"] series! --assert not none? find any-string! ref! - --assert 1 = index? find [#{00} #[string!] #[binary!]] #[binary!] - --assert 3 = index? find/only [#{00} #[string!] #[binary!]] #[binary!] + --assert 1 = index? find [#{00} #(string!) #(binary!)] #(binary!) + --assert 3 = index? find/only [#{00} #(string!) #(binary!)] #(binary!) --assert 2 = index? find/only reduce ["" string! any-string! binary!] string! --assert 3 = index? find/only reduce ["" string! any-string! binary!] any-string! @@ -53,10 +53,10 @@ Rebol [ --assert none? find reduce [%a string! any-string! binary!] string! ;; using old construction syntax - --assert none? find [#[datatype! string!] #[datatype! binary!]] #[datatype! binary!] - --assert none? find [#[datatype! string!] #[datatype! binary!]] binary! - --assert not none? find/only [#[datatype! string!] #[datatype! binary!]] #[datatype! binary!] - --assert not none? find/only [#[datatype! string!] #[datatype! binary!]] binary! + --assert none? find [#(datatype! string!) #(datatype! binary!)] #(datatype! binary!) + --assert none? find [#(datatype! string!) #(datatype! binary!)] binary! + --assert not none? find/only [#(datatype! string!) #(datatype! binary!)] #(datatype! binary!) + --assert not none? find/only [#(datatype! string!) #(datatype! binary!)] binary! ===end-group=== diff --git a/src/tests/units/date-test.r3 b/src/tests/units/date-test.r3 index 03f69d500d..82a304c300 100644 --- a/src/tests/units/date-test.r3 +++ b/src/tests/units/date-test.r3 @@ -64,27 +64,27 @@ Rebol [ ===end-group=== -===start-group=== "#[date! ...]" +===start-group=== "#(date! ...)" ;@@ https://github.com/Oldes/Rebol-issues/issues/1034 - --test-- "#[date! ...] valid" - --assert 1-Feb-0003 = #[date! 1 2 3] - --assert 1-Feb-0003/4:00 = #[date! 1 2 3 4:0] - --assert 1-Feb-0003/4:00+5:00 = #[date! 1 2 3 4:0 5:0] + --test-- "#(date! ...) valid" + --assert 1-Feb-0003 = #(date! 1 2 3) + --assert 1-Feb-0003/4:00 = #(date! 1 2 3 4:0) + --assert 1-Feb-0003/4:00+5:00 = #(date! 1 2 3 4:0 5:0) ;@@ https://github.com/Oldes/Rebol-wishes/issues/1 ;@@ https://github.com/Oldes/Rebol-issues/issues/991 - --assert 1-Jan-2000 = #[date! 1-1-2000] - --assert 1-Jan-2000/10:00 = #[date! 1-1-2000 10:0] - --assert 1-Jan-2000/10:00+2:00 = #[date! 1-1-2000 10:0 2:0] - --assert 5-Jan-2000/4:00 = #[date! 1-1-2000 100:0] - - --test-- "#[date! ...] invalid" - --assert error? try [load {#[date! 1]}] - --assert error? try [load {#[date! 1 2]}] - --assert error? try [load {#[date! 1 2 3 x]}] - --assert error? try [load {#[date! 1 2 3 4:0 x]}] - --assert error? try [load {#[date! 1 2 3 4:0 5:0 3]}] + --assert 1-Jan-2000 = #(date! 1-1-2000) + --assert 1-Jan-2000/10:00 = #(date! 1-1-2000 10:0) + --assert 1-Jan-2000/10:00+2:00 = #(date! 1-1-2000 10:0 2:0) + --assert 5-Jan-2000/4:00 = #(date! 1-1-2000 100:0) + + --test-- "#(date! ...) invalid" + --assert error? try [load {#(date! 1)}] + --assert error? try [load {#(date! 1 2)}] + --assert error? try [load {#(date! 1 2 3 x)}] + --assert error? try [load {#(date! 1 2 3 4:0 x)}] + --assert error? try [load {#(date! 1 2 3 4:0 5:0 3)}] ;@@ https://github.com/Oldes/Rebol-issues/issues/2508 - --assert datatype? try [load {#[date!]}] + --assert datatype? try [load {#(date!)}] ===end-group=== @@ -364,7 +364,7 @@ Rebol [ --test-- "query/mode date" date: 8-Apr-2020 ; no time! - --assert equal? query/mode date all-date-words [2020 4 8 #[none] 2020-04-08 #[none] #[none] #[none] #[none] 3 99 #[none] 2020-04-08 2458948.0] + --assert equal? query/mode date all-date-words [2020 4 8 #(none) 2020-04-08 #(none) #(none) #(none) #(none) 3 99 #(none) 2020-04-08 2458948.0] ===end-group=== diff --git a/src/tests/units/decimal-test.r3 b/src/tests/units/decimal-test.r3 index 96267631fe..fdaf6bfc60 100644 --- a/src/tests/units/decimal-test.r3 +++ b/src/tests/units/decimal-test.r3 @@ -211,7 +211,7 @@ Rebol [ --test-- "decimal construction" ;@@ https://github.com/Oldes/Rebol-issues/issues/1034 - --assert 1.0 = #[decimal! 1] + --assert 1.0 = #(decimal! 1) --assert error? try [load {#[decimal! 1 2]}] --test-- "decimal pick" diff --git a/src/tests/units/delect-test.r3 b/src/tests/units/delect-test.r3 index d7fbc710b9..3db66c35e0 100644 --- a/src/tests/units/delect-test.r3 +++ b/src/tests/units/delect-test.r3 @@ -33,9 +33,9 @@ if find lib 'delect [ inp: delect dialect inp out --assert out = [cmd a@b 3] inp: delect dialect inp out - --assert out = [cmd http:// #[none]] + --assert out = [cmd http:// #(none)] inp: delect dialect inp out - --assert out = [cmd #[none] 5] + --assert out = [cmd #(none) 5] ;-- should be extended with more tests... ] diff --git a/src/tests/units/dh-test.r3 b/src/tests/units/dh-test.r3 index e2dd3fe049..6995d9eb94 100644 --- a/src/tests/units/dh-test.r3 +++ b/src/tests/units/dh-test.r3 @@ -26,10 +26,10 @@ C79E915C3277361FBFA587C6DC06FEDE0B7E57FEC0B68F96B3AD651D54264357 ;- Boban and Alice both have G and P values and generates DH keys... --assert handle? k-Alice: dh-init g p - --assert "#[handle! dhm]" = mold k-Alice + --assert "#(handle! dhm)" = mold k-Alice --assert handle? k-Boban: dh-init g p - --assert "#[handle! dhm]" = mold k-Boban + --assert "#(handle! dhm)" = mold k-Boban --test-- "DH public key exportation" diff --git a/src/tests/units/error-test.r3 b/src/tests/units/error-test.r3 index b1f8be6d2d..2995da8dff 100644 --- a/src/tests/units/error-test.r3 +++ b/src/tests/units/error-test.r3 @@ -117,9 +117,9 @@ Rebol [ ] --assert assert/type [x [integer! string!]] ;@@ https://github.com/Oldes/Rebol-issues/issues/1364 - --assert assert/type [x #[typeset! [char! string!]]] + --assert assert/type [x #(typeset! [char! string!])] --assert assert/type [x any-string!] - --assert assert/type [x #[string!]] + --assert assert/type [x #(string!)] --test-- "invalid assert" ;@@ https://github.com/Oldes/Rebol-issues/issues/1363 diff --git a/src/tests/units/evaluation-test.r3 b/src/tests/units/evaluation-test.r3 index 587bfd0d11..e391d1976c 100644 --- a/src/tests/units/evaluation-test.r3 +++ b/src/tests/units/evaluation-test.r3 @@ -302,7 +302,7 @@ Rebol [ --test-- "reduce-19" b: next [1 2] --assert [2] = reduce/into [yes 3 4 5] b - --assert [1 #[true] 3 4 5 2] = head b + --assert [1 #(true) 3 4 5 2] = head b --test-- "reduce-20" b: 2 @@ -488,7 +488,7 @@ Rebol [ --test-- "to-value" ;@@ https://github.com/Oldes/Rebol-issues/issues/2003 - --assert none? to-value #[unset] + --assert none? to-value #(unset) --assert integer? to-value 1 --test-- "unset unbind 'x" @@ -519,13 +519,13 @@ Rebol [ --assert b = [4 5] --test-- "set-5" - --assert [4 #[none]] = set [A B] reduce [4 none] + --assert [4 #(none)] = set [A B] reduce [4 none] --assert a = 4 --assert b = none --test-- "set-6" b: 789 - --assert [4 #[none]] = set/some [A B] reduce [4 none] + --assert [4 #(none)] = set/some [A B] reduce [4 none] --assert a = 4 --assert b = 789 @@ -853,7 +853,7 @@ Rebol [ ] --assert all [ - #[true] == catch/quit/with [a: 1 quit a: 2] :on-catch + #(true) == catch/quit/with [a: 1 quit a: 2] :on-catch a = 1 ] @@ -1156,27 +1156,27 @@ Rebol [ --test-- "dyn-ref-7" ref: yes --assert (dyn-ref-fun/:ref 10 * 9 "hello" 789) - == [90 "hello" #[true] 789 #[none] #[none] #[none] #[none]] + == [90 "hello" #(true) 789 #(none) #(none) #(none) #(none)] --test-- "dyn-ref-8" ref: no --assert (dyn-ref-fun/:ref 10 * 9 "hello" 789) - == [90 "hello" #[none] #[none] #[none] #[none] #[none] #[none]] + == [90 "hello" #(none) #(none) #(none) #(none) #(none) #(none)] --test-- "dyn-ref-9" ref: ref2: yes --assert (dyn-ref-fun/:ref/:ref2 10 * 9 "hello" 789) - == [90 "hello" #[true] 789 #[true] #[none] #[none] #[none]] + == [90 "hello" #(true) 789 #(true) #(none) #(none) #(none)] --test-- "dyn-ref-10" ref: no ref2: yes --assert (dyn-ref-fun/:ref/:ref2 10 * 9 "hello" 789) - == [90 "hello" #[none] #[none] #[true] #[none] #[none] #[none]] + == [90 "hello" #(none) #(none) #(true) #(none) #(none) #(none)] --test-- "dyn-ref-11" ref: no ref2: ref3: yes --assert (dyn-ref-fun/:ref/:ref2/:ref3 10 * 9 "hello" 789 6 7) - == [90 "hello" #[none] #[none] #[true] #[true] 6 7] + == [90 "hello" #(none) #(none) #(true) #(true) 6 7] --test-- "dyn-ref-12" dyn-ref-12-obj: context [ @@ -1186,11 +1186,11 @@ Rebol [ bar: func [/local ref][ ref: no --assert (foo/:ref 10 * 9 "hello" 789) - == [90 "hello" #[none] #[none] #[none] #[none] #[none] #[none]] + == [90 "hello" #(none) #(none) #(none) #(none) #(none) #(none)] ref: yes --assert (foo/:ref 10 * 9 "hello" 789) - == [90 "hello" #[true] 789 #[none] #[none] #[none] #[none]] + == [90 "hello" #(true) 789 #(none) #(none) #(none) #(none)] ] ] diff --git a/src/tests/units/func-test.r3 b/src/tests/units/func-test.r3 index beaf70ebb2..bd5a6e5316 100644 --- a/src/tests/units/func-test.r3 +++ b/src/tests/units/func-test.r3 @@ -15,33 +15,33 @@ Rebol [ --test-- "no refinements" --assert all [error? e: try [fce ] e/id = 'no-arg] --assert all [error? e: try [fce 1] e/id = 'expect-arg] - --assert (fce "a") == ["a" #[none] #[none] #[none] #[none] #[none]] + --assert (fce "a") == ["a" #(none) #(none) #(none) #(none) #(none)] --test-- "simple refinements" --assert all [error? e: try [fce/ref1 "a" ] e/id = 'no-arg] --assert all [error? e: try [fce/ref1 "a" ""] e/id = 'expect-arg] - --assert (fce/ref1 "a" 1) == ["a" #[true] 1 #[none] #[none] #[none]] - --assert (fce/ref1 "a" 1 + 1) == ["a" #[true] 2 #[none] #[none] #[none]] - --assert (fce/ref1/ref2 "a" 1 x y) == ["a" #[true] 1 #[true] x y] - --assert (fce/ref2/ref1 "a" x y 1 + 1) == ["a" #[true] 2 #[true] x y] + --assert (fce/ref1 "a" 1) == ["a" #(true) 1 #(none) #(none) #(none)] + --assert (fce/ref1 "a" 1 + 1) == ["a" #(true) 2 #(none) #(none) #(none)] + --assert (fce/ref1/ref2 "a" 1 x y) == ["a" #(true) 1 #(true) x y] + --assert (fce/ref2/ref1 "a" x y 1 + 1) == ["a" #(true) 2 #(true) x y] --test-- "dynamic refinements" ref1: yes --assert all [error? e: try [fce/:ref1 "a" ] e/id = 'no-arg] ref1: off --assert all [error? e: try [fce/:ref1 "a" ] e/id = 'no-arg] ref1: yes --assert all [error? e: try [fce/:ref1 "a" ""] e/id = 'expect-arg] - ref1: off --assert (fce/:ref1 "a" "") == ["a" #[none] #[none] #[none] #[none] #[none]] - ref1: yes --assert (fce/:ref1 "a" 1) == ["a" #[true] 1 #[none] #[none] #[none]] - ref1: off --assert (fce/:ref1 "a" 1) == ["a" #[none] #[none] #[none] #[none] #[none]] - ref1: yes --assert all [(fce/:ref1 "a" x: 1 + 1) == ["a" #[true] 2 #[none] #[none] #[none]] x == 2] - ref1: off --assert all [(fce/:ref1 "a" x: 1 + 1) == ["a" #[none] #[none] #[none] #[none] #[none]] x == 2] - ref1: yes ref2: yes --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #[true] 2 #[true] x y] - ref1: yes ref2: yes --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #[true] 2 #[true] x y] - ref1: yes ref2: off --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #[true] 2 #[none] #[none] #[none]] - ref1: yes ref2: off --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #[true] 2 #[none] #[none] #[none]] - ref1: off ref2: yes --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #[none] #[none] #[true] x y] - ref1: off ref2: yes --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #[none] #[none] #[true] x y] - ref1: off ref2: off --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #[none] #[none] #[none] #[none] #[none]] - ref1: off ref2: off --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #[none] #[none] #[none] #[none] #[none]] + ref1: off --assert (fce/:ref1 "a" "") == ["a" #(none) #(none) #(none) #(none) #(none)] + ref1: yes --assert (fce/:ref1 "a" 1) == ["a" #(true) 1 #(none) #(none) #(none)] + ref1: off --assert (fce/:ref1 "a" 1) == ["a" #(none) #(none) #(none) #(none) #(none)] + ref1: yes --assert all [(fce/:ref1 "a" x: 1 + 1) == ["a" #(true) 2 #(none) #(none) #(none)] x == 2] + ref1: off --assert all [(fce/:ref1 "a" x: 1 + 1) == ["a" #(none) #(none) #(none) #(none) #(none)] x == 2] + ref1: yes ref2: yes --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #(true) 2 #(true) x y] + ref1: yes ref2: yes --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #(true) 2 #(true) x y] + ref1: yes ref2: off --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #(true) 2 #(none) #(none) #(none)] + ref1: yes ref2: off --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #(true) 2 #(none) #(none) #(none)] + ref1: off ref2: yes --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #(none) #(none) #(true) x y] + ref1: off ref2: yes --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #(none) #(none) #(true) x y] + ref1: off ref2: off --assert (fce/:ref1/:ref2 "a" 1 + 1 x y) == ["a" #(none) #(none) #(none) #(none) #(none)] + ref1: off ref2: off --assert (fce/:ref2/:ref1 "a" x y 1 + 1) == ["a" #(none) #(none) #(none) #(none) #(none)] ===end-group=== @@ -60,7 +60,7 @@ Rebol [ --test-- "apply with refinements" ;@@ https://github.com/Oldes/Rebol-issues/issues/167 f: func [a /b c] [reduce [a b c]] - --assert [1 #[true] 3] = apply :f [1 2 3] + --assert [1 #(true) 3] = apply :f [1 2 3] --test-- "apply/only" ;@@ https://github.com/Oldes/Rebol-issues/issues/105 @@ -147,8 +147,8 @@ Rebol [ f: func[/a b [integer!]][] --assert all [ block? b: types-of :f - b/1 = #[typeset! [none! logic!]] - b/2 = #[typeset! [integer!]] + b/1 = #(typeset! [none! logic!]) + b/2 = #(typeset! [integer!]) ] ===end-group=== @@ -363,7 +363,7 @@ Rebol [ f3: make :f1 [[b /local a][reduce [b a]]] --assert 2 = f1 1 --assert [2 "foo"] = f2 2 - --assert [3 #[none]] = f3 3 + --assert [3 #(none)] = f3 3 --test-- "unset as a function argument" ;@@ https://github.com/Oldes/Rebol-issues/issues/293 @@ -372,7 +372,7 @@ Rebol [ f: func [v [any-type!]] [type? get/any 'v] --assert unset! = f make unset! none f: func [v [unset!]] [type? get/any 'v] - --assert unset! = f #[unset] + --assert unset! = f #(unset) --test-- "issue-196" ;@@ https://github.com/Oldes/Rebol-issues/issues/196 diff --git a/src/tests/units/handle-test.r3 b/src/tests/units/handle-test.r3 index 11e30360f8..1c55a75e64 100644 --- a/src/tests/units/handle-test.r3 +++ b/src/tests/units/handle-test.r3 @@ -64,7 +64,7 @@ h4: aes/key #{00000000000000000000000000000000} none --assert {[#[handle! rc4] #[handle! rc4] #[handle! aes] #[handle! aes]]} = mold try [sort/reverse blk] --test-- "handle as a key in map" - m: #() + m: #[] --assert not error? try [m/(h1): 1] --assert not error? try [repend m [h2 2 h3 3]] --assert 1 = try [pick m h1] diff --git a/src/tests/units/image-test.r3 b/src/tests/units/image-test.r3 index d06ae02a60..e0db6dd0f9 100644 --- a/src/tests/units/image-test.r3 +++ b/src/tests/units/image-test.r3 @@ -44,19 +44,19 @@ Rebol [ ===start-group=== "construct image" --test-- "construct image valid" - --assert "make image! [1x1 #{FFFFFF}]" = mold #[image! 1x1] - --assert "make image! [1x1 #{FFFFFF}]" = mold #[image! 1x1 #{FFFFFF}] - --assert "make image! [1x1 #{FFFFFF}]" = mold #[image! 1x1 #{FF}] - --assert "make image! [1x1 #{141414}]" = mold #[image! 1x1 20.20.20] - --assert "make image! [1x1 #{141414} #{3C}]" = mold #[image! 1x1 20.20.20.60] + --assert "make image! [1x1 #{FFFFFF}]" = mold #(image! 1x1) + --assert "make image! [1x1 #{FFFFFF}]" = mold #(image! 1x1 #{FFFFFF}) + --assert "make image! [1x1 #{FFFFFF}]" = mold #(image! 1x1 #{FF}) + --assert "make image! [1x1 #{141414}]" = mold #(image! 1x1 20.20.20) + --assert "make image! [1x1 #{141414} #{3C}]" = mold #(image! 1x1 20.20.20.60) --assert all [ - "make image! [1x1 #{FFFFFF} #{30}]" = mold img: #[image! 1x1 #{FFFFFF} #{30}] + "make image! [1x1 #{FFFFFF} #{30}]" = mold img: #(image! 1x1 #{FFFFFF} #{30}) #{30} = img/alpha #{FFFFFF} = img/rgb #{FFFFFF30} = img/rgba ] --assert all [ - "make image! [1x1 #{}]" = mold img: #[image! 1x1 #{FFFFFF} 2] + "make image! [1x1 #{}]" = mold img: #(image! 1x1 #{FFFFFF} 2) 2 = index? img #{} = img/alpha #{} = img/rgba @@ -67,17 +67,17 @@ Rebol [ ] --test-- "construct image invalid" ;@@ https://github.com/Oldes/Rebol-issues/issues/1034 - --assert error? try [load {#[image! x]}] - --assert error? try [load {#[image! 1x-1]}] - --assert error? try [load {#[image! 1x1 x]}] - --assert error? try [load {#[image! 1x1 #{FF} x]}] - --assert error? try [load {#[image! 1x1 20.20.20.60 x]}] - --assert error? try [load {#[image! 1x1 #{FFFFFF} #{30} x]}] + --assert error? try [load {#(image! x)}] + --assert error? try [load {#(image! 1x-1)}] + --assert error? try [load {#(image! 1x1 x)}] + --assert error? try [load {#(image! 1x1 #{FF} x)}] + --assert error? try [load {#(image! 1x1 20.20.20.60 x)}] + --assert error? try [load {#(image! 1x1 #{FFFFFF} #{30} x)}] ;@@ https://github.com/Oldes/Rebol-issues/issues/1037 --assert all [error? e: try [make image! [3x2 #{000000000000000000000000000000000000} 1x0]] e/id = 'malconstruct] - --assert all [error? e: try [load {#[image! 3x2 #{000000000000000000000000000000000000} 1x0]}] e/id = 'malconstruct] + --assert all [error? e: try [load {#(image! 3x2 #{000000000000000000000000000000000000} 1x0)}] e/id = 'malconstruct] ;@@ https://github.com/Oldes/Rebol-issues/issues/2508 - --assert datatype? try [load {#[image!]}] + --assert datatype? try [load {#(image!)}] ===end-group=== diff --git a/src/tests/units/lexer-test.r3 b/src/tests/units/lexer-test.r3 index a2b85a49d8..d1083a4a64 100644 --- a/src/tests/units/lexer-test.r3 +++ b/src/tests/units/lexer-test.r3 @@ -31,7 +31,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/1329 --assert all [error? e: try[transcode/one ""] e/id = 'past-end] --assert all [error? e: transcode/one/error "" e/id = 'past-end] - --assert unset? transcode/one "#[unset]" + --assert unset? transcode/one "#(unset)" --assert [] = transcode/one "[]" --assert 1 = transcode/one "1 2" --assert [1 2] = transcode/one "[1 2]" @@ -59,15 +59,15 @@ Rebol [ ] ;@@ https://github.com/Oldes/Rebol-issues/issues/1857 --assert all [ - error? e: transcode/one/error "#[block! 1]" + error? e: transcode/one/error "#(block! 1)" e/id = 'malconstruct ] --assert all [ - error? e: transcode/one/error "#[block! [1d]" + error? e: transcode/one/error "#(block! [1d)" e/id = 'malconstruct ] --assert all [ - error? e: transcode/one/error "#[" + error? e: transcode/one/error "#(" e/id = 'missing e/arg1 = "end-of-script" ] @@ -77,10 +77,10 @@ Rebol [ ===start-group=== "Invalid construction" --test-- "Invalid MAP" - --assert error? err: try [load {#(x)}] + --assert error? err: try [load {#[x]}] --assert err/id = 'invalid-arg - --assert error? err: try [load {#(x}] - --assert all [err/id = 'missing err/arg1 = "end-of-script" err/arg2 = ")"] + --assert error? err: try [load {#[x}] + --assert all [err/id = 'missing err/arg1 = "end-of-script" err/arg2 = "]"] --test-- "Invalid word" ;@@ https://github.com/Oldes/Rebol-issues/issues/22 @@ -91,7 +91,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/122 --assert error? try [load "1234#"] ;@@ https://github.com/oldes/rebol-issues/issues/2297 - --assert error? try [load {#}] ; originally (in R3-alpha) it was same like #[none] + --assert error? try [load {#}] ; originally (in R3-alpha) it was same like #(none) --test-- "Multiple leading / in refinement!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1855 @@ -136,15 +136,15 @@ Rebol [ --test-- "Invalid serialized value" ;@@ https://github.com/Oldes/Rebol-issues/issues/1429 - --assert all [error? e: try [load {1#[logic! 1]}] e/id = 'invalid] - --assert all [error? e: try [load {a#[logic! 1]}] e/id = 'invalid] + --assert all [error? e: try [load {1#(logic! 1)}] e/id = 'invalid] + --assert all [error? e: try [load {a#(logic! 1)}] e/id = 'invalid] --test-- "Invalid char" --assert all [error? e: try [load {2#"a"}] e/id = 'invalid] --test-- "Invalid path construction" ;@@ https://github.com/Oldes/Rebol-issues/issues/863 - --assert all [error? e: try [load {#[path! [0]]}] e/id = 'malconstruct] + --assert all [error? e: try [load {#(path! [0])}] e/id = 'malconstruct] --test-- "Invalid file" ;@@ https://github.com/Oldes/Rebol-issues/issues/1415 @@ -519,7 +519,7 @@ Rebol [ --test-- "sign-before-pound-1" --assert [- #"a"] = (load {-#"a"}) --test-- "sign-before-pound-2" --assert [+ #"a"] = (load {+#"a"}) --test-- "sign-before-pound-3" --assert [- #{00}] = try [load {-#{00}}] - --test-- "sign-before-pound-4" --assert [- #[none]] = try [load {-#[none]}] + --test-- "sign-before-pound-4" --assert [- #(none)] = try [load {-#(none)}] --test-- "sign-before-pound-5" --assert word! = try [type? first load {+#"a"}] --test-- "sign-before-pound-6" --assert [- #hhh] = try [load {-#hhh}] ;above is now consistent with: @@ -534,91 +534,91 @@ Rebol [ ===start-group=== "Construction syntax" --test-- {any-string!} - --assert "ab" = load {#[string! "ab"]} - --assert "b" = load {#[string! "ab" 2]} - --assert %ab = load {#[file! "ab"]} - --assert %b = load {#[file! "ab" 2]} - --assert struct? load {#[struct! [a [uint8!]]]} + --assert "ab" = load {#(string! "ab")} + --assert "b" = load {#(string! "ab" 2)} + --assert %ab = load {#(file! "ab")} + --assert %b = load {#(file! "ab" 2)} + --assert struct? load {#(struct! [a [uint8!]])} ;@@ https://github.com/Oldes/Rebol-issues/issues/1034 - --assert error? try [load {#[string! "ab" 2 x]}] - --assert error? try [load {#[file! "ab" x]}] - --assert error? try [load {#[file! "ab" 2 x]}] - --assert error? try [load {#[string! "ab" x]}] - --assert error? try [load {#[string! "ab" 2 x]}] - --assert error? try [load {#[file! "ab" x]}] - --assert error? try [load {#[file! "ab" 2 x]}] + --assert error? try [load {#(string! "ab" 2 x)}] + --assert error? try [load {#(file! "ab" x)}] + --assert error? try [load {#(file! "ab" 2 x)}] + --assert error? try [load {#(string! "ab" x)}] + --assert error? try [load {#(string! "ab" 2 x)}] + --assert error? try [load {#(file! "ab" x)}] + --assert error? try [load {#(file! "ab" 2 x)}] --test-- {object!} ;@@ https://github.com/Oldes/Rebol-issues/issues/864 - --assert block? try [transcode "#[object! [a: 1 b: 2]]"] - --assert block? try [transcode/only "#[object! [a: 1 b: 2]]"] - --assert object? try [transcode/one "#[object! [a: 1 b: 2]]"] + --assert block? try [transcode "#(object! [a: 1 b: 2])"] + --assert block? try [transcode/only "#(object! [a: 1 b: 2])"] + --assert object? try [transcode/one "#(object! [a: 1 b: 2])"] --test-- {function!} ;@@ https://github.com/Oldes/Rebol-issues/issues/1114 - --assert function? transcode/one {#[function! [[a [series!]][print a]]]} + --assert function? transcode/one {#(function! [[a [series!]][print a]])} --test-- {datatype!} ;@@ https://github.com/Oldes/Rebol-issues/issues/2508 - --assert datatype? transcode/one {#[unset!]} - --assert datatype? transcode/one {#[none!]} - --assert datatype? transcode/one {#[logic!]} - --assert datatype? transcode/one {#[integer!]} - --assert datatype? transcode/one {#[decimal!]} - --assert datatype? transcode/one {#[percent!]} - --assert datatype? transcode/one {#[money!]} - --assert datatype? transcode/one {#[char!]} - --assert datatype? transcode/one {#[pair!]} - --assert datatype? transcode/one {#[tuple!]} - --assert datatype? transcode/one {#[time!]} - --assert datatype? transcode/one {#[date!]} - --assert datatype? transcode/one {#[binary!]} - --assert datatype? transcode/one {#[string!]} - --assert datatype? transcode/one {#[file!]} - --assert datatype? transcode/one {#[email!]} - --assert datatype? transcode/one {#[ref!]} - --assert datatype? transcode/one {#[url!]} - --assert datatype? transcode/one {#[tag!]} - --assert datatype? transcode/one {#[bitset!]} - --assert datatype? transcode/one {#[image!]} - --assert datatype? transcode/one {#[vector!]} - --assert datatype? transcode/one {#[block!]} - --assert datatype? transcode/one {#[paren!]} - --assert datatype? transcode/one {#[path!]} - --assert datatype? transcode/one {#[set-path!]} - --assert datatype? transcode/one {#[get-path!]} - --assert datatype? transcode/one {#[lit-path!]} - --assert datatype? transcode/one {#[map!]} - --assert datatype? transcode/one {#[datatype!]} - --assert datatype? transcode/one {#[typeset!]} - --assert datatype? transcode/one {#[word!]} - --assert datatype? transcode/one {#[set-word!]} - --assert datatype? transcode/one {#[get-word!]} - --assert datatype? transcode/one {#[lit-word!]} - --assert datatype? transcode/one {#[refinement!]} - --assert datatype? transcode/one {#[issue!]} - --assert datatype? transcode/one {#[native!]} - --assert datatype? transcode/one {#[action!]} - --assert datatype? transcode/one {#[rebcode!]} - --assert datatype? transcode/one {#[command!]} - --assert datatype? transcode/one {#[op!]} - --assert datatype? transcode/one {#[closure!]} - --assert datatype? transcode/one {#[function!]} - --assert datatype? transcode/one {#[frame!]} - --assert datatype? transcode/one {#[object!]} - --assert datatype? transcode/one {#[module!]} - --assert datatype? transcode/one {#[error!]} - --assert datatype? transcode/one {#[task!]} - --assert datatype? transcode/one {#[port!]} - --assert datatype? transcode/one {#[gob!]} - --assert datatype? transcode/one {#[event!]} - --assert datatype? transcode/one {#[handle!]} - --assert datatype? transcode/one {#[struct!]} - --assert datatype? transcode/one {#[library!]} - --assert datatype? transcode/one {#[utype!]} + --assert datatype? transcode/one {#(unset!)} + --assert datatype? transcode/one {#(none!)} + --assert datatype? transcode/one {#(logic!)} + --assert datatype? transcode/one {#(integer!)} + --assert datatype? transcode/one {#(decimal!)} + --assert datatype? transcode/one {#(percent!)} + --assert datatype? transcode/one {#(money!)} + --assert datatype? transcode/one {#(char!)} + --assert datatype? transcode/one {#(pair!)} + --assert datatype? transcode/one {#(tuple!)} + --assert datatype? transcode/one {#(time!)} + --assert datatype? transcode/one {#(date!)} + --assert datatype? transcode/one {#(binary!)} + --assert datatype? transcode/one {#(string!)} + --assert datatype? transcode/one {#(file!)} + --assert datatype? transcode/one {#(email!)} + --assert datatype? transcode/one {#(ref!)} + --assert datatype? transcode/one {#(url!)} + --assert datatype? transcode/one {#(tag!)} + --assert datatype? transcode/one {#(bitset!)} + --assert datatype? transcode/one {#(image!)} + --assert datatype? transcode/one {#(vector!)} + --assert datatype? transcode/one {#(block!)} + --assert datatype? transcode/one {#(paren!)} + --assert datatype? transcode/one {#(path!)} + --assert datatype? transcode/one {#(set-path!)} + --assert datatype? transcode/one {#(get-path!)} + --assert datatype? transcode/one {#(lit-path!)} + --assert datatype? transcode/one {#(map!)} + --assert datatype? transcode/one {#(datatype!)} + --assert datatype? transcode/one {#(typeset!)} + --assert datatype? transcode/one {#(word!)} + --assert datatype? transcode/one {#(set-word!)} + --assert datatype? transcode/one {#(get-word!)} + --assert datatype? transcode/one {#(lit-word!)} + --assert datatype? transcode/one {#(refinement!)} + --assert datatype? transcode/one {#(issue!)} + --assert datatype? transcode/one {#(native!)} + --assert datatype? transcode/one {#(action!)} + --assert datatype? transcode/one {#(rebcode!)} + --assert datatype? transcode/one {#(command!)} + --assert datatype? transcode/one {#(op!)} + --assert datatype? transcode/one {#(closure!)} + --assert datatype? transcode/one {#(function!)} + --assert datatype? transcode/one {#(frame!)} + --assert datatype? transcode/one {#(object!)} + --assert datatype? transcode/one {#(module!)} + --assert datatype? transcode/one {#(error!)} + --assert datatype? transcode/one {#(task!)} + --assert datatype? transcode/one {#(port!)} + --assert datatype? transcode/one {#(gob!)} + --assert datatype? transcode/one {#(event!)} + --assert datatype? transcode/one {#(handle!)} + --assert datatype? transcode/one {#(struct!)} + --assert datatype? transcode/one {#(library!)} + --assert datatype? transcode/one {#(utype!)} --test-- {direct values} - --assert logic? transcode/one {#[true]} - --assert logic? transcode/one {#[false]} - --assert none? transcode/one {#[none]} - --assert unset? transcode/one {#[unset]} + --assert logic? transcode/one {#(true)} + --assert logic? transcode/one {#(false)} + --assert none? transcode/one {#(none)} + --assert unset? transcode/one {#(unset)} ===end-group=== diff --git a/src/tests/units/load-test.r3 b/src/tests/units/load-test.r3 index bf51ac2e0b..0d2df3112f 100644 --- a/src/tests/units/load-test.r3 +++ b/src/tests/units/load-test.r3 @@ -104,7 +104,7 @@ Rebol [ ] --test-- "loading an unset value" - --assert unset? try [load "#[unset]"] ;- no error + --assert unset? try [load "#(unset)"] ;- no error ===end-group=== diff --git a/src/tests/units/make-test.r3 b/src/tests/units/make-test.r3 index 9ac8743c3c..08b18f2fe9 100644 --- a/src/tests/units/make-test.r3 +++ b/src/tests/units/make-test.r3 @@ -247,9 +247,9 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/925 --test-- "make pair! .." --assert 1x1 = make pair! "1x1" - --assert error? try [make pair! quote #[unset] ] ; unset! - --assert error? try [make pair! quote #[none] ] ; none! - --assert error? try [make pair! quote #[true] ] ; logic! + --assert error? try [make pair! quote #(unset) ] ; unset! + --assert error? try [make pair! quote #(none) ] ; none! + --assert error? try [make pair! quote #(true) ] ; logic! --assert 1x1 = try [make pair! quote 1 ] ; integer! --assert 0x0 = try [make pair! quote 0 ] ; integer! --assert 4x4 = try [make pair! quote 4 ] ; integer! @@ -278,16 +278,16 @@ Rebol [ --assert error? try [make pair! quote :a/b ] ; get-path! --assert error? try [make pair! quote /ref ] ; refinement! --assert error? try [make pair! quote #FF ] ; issue! - --assert error? try [make pair! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make pair! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [make pair! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [make pair! quote #[object! [a: 1]] ] ; object! - --assert error? try [make pair! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make pair! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make pair! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [make pair! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [make pair! quote #(object! [a: 1]) ] ; object! + --assert error? try [make pair! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to pair! .." --assert 1x1 = to pair! "1x1" - --assert error? try [to pair! quote #[unset] ] ; unset! - --assert error? try [to pair! quote #[none] ] ; none! - --assert error? try [to pair! quote #[true] ] ; logic! + --assert error? try [to pair! quote #(unset) ] ; unset! + --assert error? try [to pair! quote #(none) ] ; none! + --assert error? try [to pair! quote #(true) ] ; logic! --assert 1x1 = try [to pair! quote 1 ] ; integer! --assert 0x0 = try [to pair! quote 0 ] ; integer! --assert 4x4 = try [to pair! quote 4 ] ; integer! @@ -315,11 +315,11 @@ Rebol [ --assert error? try [to pair! quote :a/b ] ; get-path! --assert error? try [to pair! quote /ref ] ; refinement! --assert error? try [to pair! quote #FF ] ; issue! - --assert error? try [to pair! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [to pair! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [to pair! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [to pair! quote #[object! [a: 1]] ] ; object! - --assert error? try [to pair! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [to pair! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [to pair! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [to pair! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [to pair! quote #(object! [a: 1]) ] ; object! + --assert error? try [to pair! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to pair! string! (long)" ;@@ https://github.com/Oldes/Rebol-issues/issues/2202 ; using mold because of rounding error causing false comparison @@ -333,78 +333,78 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/951 ;@@ https://github.com/Oldes/Rebol-issues/issues/2055 --test-- "make logic! .." - --assert #[true] = try [make logic! quote #[unset] ] ; unset! - --assert #[false] = try [make logic! quote #[none] ] ; none! - --assert #[true] = try [make logic! quote #[true] ] ; logic! - --assert #[true] = try [make logic! quote 1 ] ; integer! - --assert #[false] = try [make logic! quote 0 ] ; integer! - --assert #[true] = try [make logic! quote 4 ] ; integer! - --assert #[true] = try [make logic! quote 4.0 ] ; decimal! - --assert #[true] = try [make logic! quote 4.0000000000000001% ] ; percent! - --assert #[true] = try [make logic! quote $4 ] ; money! - --assert #[true] = try [make logic! quote #"a" ] ; char! - --assert #[true] = try [make logic! quote 2x2 ] ; pair! - --assert #[true] = try [make logic! quote 1.1.1 ] ; tuple! - --assert #[true] = try [make logic! quote 10:00 ] ; time! - --assert #[true] = try [make logic! quote 2000-01-01 ] ; date! - --assert #[true] = try [make logic! quote #{00} ] ; binary! - --assert #[true] = try [make logic! quote #{312032} ] ; binary! - --assert #[true] = try [make logic! quote "" ] ; string! - --assert #[true] = try [make logic! quote "1 2" ] ; string! - --assert #[true] = try [make logic! quote %file ] ; file! - --assert #[true] = try [make logic! quote u@email ] ; email! - --assert #[true] = try [make logic! quote #[ref! "ref"] ] ; ref! - --assert #[true] = try [make logic! quote http://aa ] ; url! - --assert #[true] = try [make logic! quote ] ; tag! - --assert #[true] = try [make logic! quote [] ] ; empty block! - --assert #[true] = try [make logic! quote [1 2] ] ; block! - --assert #[true] = try [make logic! quote (1 2) ] ; paren! - --assert #[true] = try [make logic! quote a/b ] ; path! - --assert #[true] = try [make logic! quote a/b: ] ; set-path! - --assert #[true] = try [make logic! quote :a/b ] ; get-path! - --assert #[true] = try [make logic! quote /ref ] ; refinement! - --assert #[true] = try [make logic! quote #FF ] ; issue! - --assert #[true] = try [make logic! quote #[bitset! #{FF}] ] ; bitset! - --assert #[true] = try [make logic! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert #[true] = try [make logic! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert #[true] = try [make logic! quote #[object! [a: 1]] ] ; object! - --assert #[true] = try [make logic! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert #(true) = try [make logic! quote #(unset) ] ; unset! + --assert #(false) = try [make logic! quote #(none) ] ; none! + --assert #(true) = try [make logic! quote #(true) ] ; logic! + --assert #(true) = try [make logic! quote 1 ] ; integer! + --assert #(false) = try [make logic! quote 0 ] ; integer! + --assert #(true) = try [make logic! quote 4 ] ; integer! + --assert #(true) = try [make logic! quote 4.0 ] ; decimal! + --assert #(true) = try [make logic! quote 4.0000000000000001% ] ; percent! + --assert #(true) = try [make logic! quote $4 ] ; money! + --assert #(true) = try [make logic! quote #"a" ] ; char! + --assert #(true) = try [make logic! quote 2x2 ] ; pair! + --assert #(true) = try [make logic! quote 1.1.1 ] ; tuple! + --assert #(true) = try [make logic! quote 10:00 ] ; time! + --assert #(true) = try [make logic! quote 2000-01-01 ] ; date! + --assert #(true) = try [make logic! quote #{00} ] ; binary! + --assert #(true) = try [make logic! quote #{312032} ] ; binary! + --assert #(true) = try [make logic! quote "" ] ; string! + --assert #(true) = try [make logic! quote "1 2" ] ; string! + --assert #(true) = try [make logic! quote %file ] ; file! + --assert #(true) = try [make logic! quote u@email ] ; email! + --assert #(true) = try [make logic! quote #(ref! "ref") ] ; ref! + --assert #(true) = try [make logic! quote http://aa ] ; url! + --assert #(true) = try [make logic! quote ] ; tag! + --assert #(true) = try [make logic! quote [] ] ; empty block! + --assert #(true) = try [make logic! quote [1 2] ] ; block! + --assert #(true) = try [make logic! quote (1 2) ] ; paren! + --assert #(true) = try [make logic! quote a/b ] ; path! + --assert #(true) = try [make logic! quote a/b: ] ; set-path! + --assert #(true) = try [make logic! quote :a/b ] ; get-path! + --assert #(true) = try [make logic! quote /ref ] ; refinement! + --assert #(true) = try [make logic! quote #FF ] ; issue! + --assert #(true) = try [make logic! quote #(bitset! #{FF}) ] ; bitset! + --assert #(true) = try [make logic! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert #(true) = try [make logic! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert #(true) = try [make logic! quote #(object! [a: 1]) ] ; object! + --assert #(true) = try [make logic! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to logic! .." - --assert #[true] = try [to logic! quote #[unset] ] ; unset! - --assert #[false] = try [to logic! quote #[none] ] ; none! - --assert #[true] = try [to logic! quote #[true] ] ; logic! - --assert #[true] = try [to logic! quote 1 ] ; integer! - --assert #[true] = try [to logic! quote 0 ] ; integer! - --assert #[true] = try [to logic! quote 4 ] ; integer! - --assert #[true] = try [to logic! quote 4.0 ] ; decimal! - --assert #[true] = try [to logic! quote 4.0000000000000001% ] ; percent! - --assert #[true] = try [to logic! quote $4 ] ; money! - --assert #[true] = try [to logic! quote #"a" ] ; char! - --assert #[true] = try [to logic! quote 2x2 ] ; pair! - --assert #[true] = try [to logic! quote 1.1.1 ] ; tuple! - --assert #[true] = try [to logic! quote 10:00 ] ; time! - --assert #[true] = try [to logic! quote 2000-01-01 ] ; date! - --assert #[true] = try [to logic! quote #{00} ] ; binary! - --assert #[true] = try [to logic! quote #{312032} ] ; binary! - --assert #[true] = try [to logic! quote "" ] ; string! - --assert #[true] = try [to logic! quote "1 2" ] ; string! - --assert #[true] = try [to logic! quote %file ] ; file! - --assert #[true] = try [to logic! quote u@email ] ; email! - --assert #[true] = try [to logic! quote #[ref! "ref"] ] ; ref! - --assert #[true] = try [to logic! quote http://aa ] ; url! - --assert #[true] = try [to logic! quote ] ; tag! - --assert #[true] = try [to logic! quote [1 2] ] ; block! - --assert #[true] = try [to logic! quote (1 2) ] ; paren! - --assert #[true] = try [to logic! quote a/b ] ; path! - --assert #[true] = try [to logic! quote a/b: ] ; set-path! - --assert #[true] = try [to logic! quote :a/b ] ; get-path! - --assert #[true] = try [to logic! quote /ref ] ; refinement! - --assert #[true] = try [to logic! quote #FF ] ; issue! - --assert #[true] = try [to logic! quote #[bitset! #{FF}] ] ; bitset! - --assert #[true] = try [to logic! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert #[true] = try [to logic! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert #[true] = try [to logic! quote #[object! [a: 1]] ] ; object! - --assert #[true] = try [to logic! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert #(true) = try [to logic! quote #(unset) ] ; unset! + --assert #(false) = try [to logic! quote #(none) ] ; none! + --assert #(true) = try [to logic! quote #(true) ] ; logic! + --assert #(true) = try [to logic! quote 1 ] ; integer! + --assert #(true) = try [to logic! quote 0 ] ; integer! + --assert #(true) = try [to logic! quote 4 ] ; integer! + --assert #(true) = try [to logic! quote 4.0 ] ; decimal! + --assert #(true) = try [to logic! quote 4.0000000000000001% ] ; percent! + --assert #(true) = try [to logic! quote $4 ] ; money! + --assert #(true) = try [to logic! quote #"a" ] ; char! + --assert #(true) = try [to logic! quote 2x2 ] ; pair! + --assert #(true) = try [to logic! quote 1.1.1 ] ; tuple! + --assert #(true) = try [to logic! quote 10:00 ] ; time! + --assert #(true) = try [to logic! quote 2000-01-01 ] ; date! + --assert #(true) = try [to logic! quote #{00} ] ; binary! + --assert #(true) = try [to logic! quote #{312032} ] ; binary! + --assert #(true) = try [to logic! quote "" ] ; string! + --assert #(true) = try [to logic! quote "1 2" ] ; string! + --assert #(true) = try [to logic! quote %file ] ; file! + --assert #(true) = try [to logic! quote u@email ] ; email! + --assert #(true) = try [to logic! quote #(ref! "ref") ] ; ref! + --assert #(true) = try [to logic! quote http://aa ] ; url! + --assert #(true) = try [to logic! quote ] ; tag! + --assert #(true) = try [to logic! quote [1 2] ] ; block! + --assert #(true) = try [to logic! quote (1 2) ] ; paren! + --assert #(true) = try [to logic! quote a/b ] ; path! + --assert #(true) = try [to logic! quote a/b: ] ; set-path! + --assert #(true) = try [to logic! quote :a/b ] ; get-path! + --assert #(true) = try [to logic! quote /ref ] ; refinement! + --assert #(true) = try [to logic! quote #FF ] ; issue! + --assert #(true) = try [to logic! quote #(bitset! #{FF}) ] ; bitset! + --assert #(true) = try [to logic! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert #(true) = try [to logic! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert #(true) = try [to logic! quote #(object! [a: 1]) ] ; object! + --assert #(true) = try [to logic! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== @@ -431,9 +431,9 @@ Rebol [ ===start-group=== "make/to block!" ;@@ https://github.com/Oldes/Rebol-issues/issues/2056 --test-- "make block! .." - --assert error? try [make block! quote #[unset] ] ; unset! - --assert error? try [make block! quote #[none] ] ; none! - --assert error? try [make block! quote #[true] ] ; logic! + --assert error? try [make block! quote #(unset) ] ; unset! + --assert error? try [make block! quote #(none) ] ; none! + --assert error? try [make block! quote #(true) ] ; logic! --assert [] = try [make block! quote 4 ] ; integer! --assert [] = try [make block! quote 4.0 ] ; decimal! --assert error? try [make block! quote 4% ] ; percent! @@ -461,16 +461,16 @@ Rebol [ --assert [a b] = try [make block! quote :a/b ] ; get-path! --assert error? try [make block! quote /ref ] ; refinement! --assert error? try [make block! quote #FF ] ; issue! - --assert error? try [make block! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make block! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert [0 0] = try [make block! quote #[u32! 2 [0 0]] ] ; vector! - --assert [a: 1] = try [make block! quote #[object! [a: 1]] ] ; object! - --assert error? try [make block! #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make block! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make block! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert [0 0] = try [make block! quote #(u32! 2 [0 0]) ] ; vector! + --assert [a: 1] = try [make block! quote #(object! [a: 1]) ] ; object! + --assert error? try [make block! #(typeset! [integer! percent!]) ] ; typeset! --test-- "to block! .." - --assert [#[unset]] = try [to block! quote #[unset] ] ; unset! - --assert [#[none]] = try [to block! quote #[none] ] ; none! - --assert [#[true]] = try [to block! quote #[true] ] ; logic! + --assert [#(unset)] = try [to block! quote #(unset) ] ; unset! + --assert [#(none)] = try [to block! quote #(none) ] ; none! + --assert [#(true)] = try [to block! quote #(true) ] ; logic! --assert [4] = try [to block! quote 4 ] ; integer! --assert [4.0] = try [to block! quote 4.0 ] ; decimal! --assert [4%] = try [to block! quote 4% ] ; percent! @@ -496,11 +496,11 @@ Rebol [ --assert [a b] = try [to block! quote :a/b ] ; get-path! --assert [/ref] = try [to block! quote /ref ] ; refinement! --assert [#FF] = try [to block! quote #FF ] ; issue! - --assert [0 0] = try [to block! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert [a: 1] = try [to block! quote #[object! [a: 1]] ] ; object! - --assert [#[bitset! #{FF}]] = try [to block! quote #[bitset! #{FF}] ] ; bitset! - --assert [#[image! 1x1 #{FFFFFF}]] = try [to block! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert [#[integer!] #[percent!]] = try [to block! #[typeset! [integer! percent!]] ] ; typeset! + --assert [0 0] = try [to block! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert [a: 1] = try [to block! quote #(object! [a: 1]) ] ; object! + --assert [#(bitset! #{FF})] = try [to block! quote #(bitset! #{FF}) ] ; bitset! + --assert [#(image! 1x1 #{FFFFFF})] = try [to block! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert [#(integer!) #(percent!)] = try [to block! #(typeset! [integer! percent!]) ] ; typeset! ;@@ https://github.com/Oldes/Rebol-issues/issues/2090 --assert [a %b/c] = to block! 'a/%b/c --assert [a %b c] = to block! 'a/%"b"/c @@ -509,9 +509,9 @@ Rebol [ ===start-group=== "make/to path" ;@@ https://github.com/Oldes/Rebol-issues/issues/2451 --test-- "make path! .." - --assert error? try [make path! quote #[unset] ] ; unset! - --assert error? try [make path! quote #[none] ] ; none! - --assert error? try [make path! quote #[true] ] ; logic! + --assert error? try [make path! quote #(unset) ] ; unset! + --assert error? try [make path! quote #(none) ] ; none! + --assert error? try [make path! quote #(true) ] ; logic! --assert path? try [make path! quote 1 ] ; integer! --assert path? try [make path! quote 0 ] ; integer! --assert path? try [make path! quote 4 ] ; integer! @@ -529,7 +529,7 @@ Rebol [ --assert path? try [make path! quote "1 2" ] ; string! --assert error? try [make path! quote %file ] ; file! --assert error? try [make path! quote u@email ] ; email! - --assert error? try [make path! quote #[ref! "ref"] ] ; ref! + --assert error? try [make path! quote #(ref! "ref") ] ; ref! --assert error? try [make path! quote http://aa ] ; url! --assert error? try [make path! quote ] ; tag! --assert path? try [make path! quote [1 2] ] ; block! @@ -539,16 +539,16 @@ Rebol [ --assert path? try [make path! quote :a/b ] ; get-path! --assert error? try [make path! quote /ref ] ; refinement! --assert error? try [make path! quote #FF ] ; issue! - --assert error? try [make path! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make path! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert path? try [make path! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert path? try [make path! quote #[object! [a: 1]] ] ; object! - --assert error? try [make path! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make path! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make path! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert path? try [make path! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert path? try [make path! quote #(object! [a: 1]) ] ; object! + --assert error? try [make path! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to path! .." - --assert path? try [to path! quote #[unset] ] ; unset! - --assert path? try [to path! quote #[none] ] ; none! - --assert path? try [to path! quote #[true] ] ; logic! + --assert path? try [to path! quote #(unset) ] ; unset! + --assert path? try [to path! quote #(none) ] ; none! + --assert path? try [to path! quote #(true) ] ; logic! --assert path? try [to path! quote 1 ] ; integer! --assert path? try [to path! quote 0 ] ; integer! --assert path? try [to path! quote 4 ] ; integer! @@ -566,7 +566,7 @@ Rebol [ --assert path? try [to path! quote "1 2" ] ; string! --assert path? try [to path! quote %file ] ; file! --assert path? try [to path! quote u@email ] ; email! - --assert path? try [to path! quote #[ref! "ref"] ] ; ref! + --assert path? try [to path! quote #(ref! "ref") ] ; ref! --assert path? try [to path! quote http://aa ] ; url! --assert path? try [to path! quote ] ; tag! --assert path? try [to path! quote [1 2] ] ; block! @@ -576,20 +576,20 @@ Rebol [ --assert path? try [to path! quote :a/b ] ; get-path! --assert path? try [to path! quote /ref ] ; refinement! --assert path? try [to path! quote #FF ] ; issue! - --assert path? try [to path! quote #[bitset! #{FF}] ] ; bitset! - --assert path? try [to path! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert path? try [to path! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert path? try [to path! quote #[object! [a: 1]] ] ; object! - --assert path? try [to path! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert path? try [to path! quote #(bitset! #{FF}) ] ; bitset! + --assert path? try [to path! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert path? try [to path! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert path? try [to path! quote #(object! [a: 1]) ] ; object! + --assert path? try [to path! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== ===start-group=== "make/to map" ;@@ https://github.com/Oldes/Rebol-issues/issues/982 ;@@ https://github.com/Oldes/Rebol-issues/issues/2451 --test-- "make map! .." - --assert error? try [make map! quote #[unset] ] ; unset! - --assert error? try [make map! quote #[none] ] ; none! - --assert error? try [make map! quote #[true] ] ; logic! + --assert error? try [make map! quote #(unset) ] ; unset! + --assert error? try [make map! quote #(none) ] ; none! + --assert error? try [make map! quote #(true) ] ; logic! --assert map? try [make map! quote 1 ] ; integer! --assert map? try [make map! quote 0 ] ; integer! --assert map? try [make map! quote 4 ] ; integer! @@ -607,7 +607,7 @@ Rebol [ --assert error? try [make map! quote "1 2" ] ; string! --assert error? try [make map! quote %file ] ; file! --assert error? try [make map! quote u@email ] ; email! - --assert error? try [make map! quote #[ref! "ref"] ] ; ref! + --assert error? try [make map! quote #(ref! "ref") ] ; ref! --assert error? try [make map! quote http://aa ] ; url! --assert error? try [make map! quote ] ; tag! --assert map? try [make map! quote [1 2] ] ; block! @@ -617,15 +617,15 @@ Rebol [ --assert error? try [make map! quote :a/b ] ; get-path! --assert error? try [make map! quote /ref ] ; refinement! --assert error? try [make map! quote #FF ] ; issue! - --assert error? try [make map! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make map! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [make map! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert map? try [make map! quote #[object! [a: 1]] ] ; object! - --assert error? try [make map! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make map! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make map! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [make map! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert map? try [make map! quote #(object! [a: 1]) ] ; object! + --assert error? try [make map! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to map! .." - --assert error? try [to map! quote #[unset] ] ; unset! - --assert error? try [to map! quote #[none] ] ; none! - --assert error? try [to map! quote #[true] ] ; logic! + --assert error? try [to map! quote #(unset) ] ; unset! + --assert error? try [to map! quote #(none) ] ; none! + --assert error? try [to map! quote #(true) ] ; logic! --assert error? try [to map! quote 1 ] ; integer! --assert error? try [to map! quote 0 ] ; integer! --assert error? try [to map! quote 4 ] ; integer! @@ -643,7 +643,7 @@ Rebol [ --assert error? try [to map! quote "1 2" ] ; string! --assert error? try [to map! quote %file ] ; file! --assert error? try [to map! quote u@email ] ; email! - --assert error? try [to map! quote #[ref! "ref"] ] ; ref! + --assert error? try [to map! quote #(ref! "ref") ] ; ref! --assert error? try [to map! quote http://aa ] ; url! --assert error? try [to map! quote ] ; tag! --assert map? try [to map! quote [1 2] ] ; block! @@ -653,19 +653,19 @@ Rebol [ --assert error? try [to map! quote :a/b ] ; get-path! --assert error? try [to map! quote /ref ] ; refinement! --assert error? try [to map! quote #FF ] ; issue! - --assert error? try [to map! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [to map! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [to map! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert map? try [to map! quote #[object! [a: 1]] ] ; object! - --assert error? try [to map! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [to map! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [to map! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [to map! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert map? try [to map! quote #(object! [a: 1]) ] ; object! + --assert error? try [to map! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== ===start-group=== "make/to string" ;@@ https://github.com/Oldes/Rebol-issues/issues/2073 --test-- "make string! ..." - --assert "" = try [make string! quote #[unset] ] ; unset! - --assert error? try [make string! quote #[none] ] ; none! - --assert "true" = try [make string! quote #[true] ] ; logic! + --assert "" = try [make string! quote #(unset) ] ; unset! + --assert error? try [make string! quote #(none) ] ; none! + --assert "true" = try [make string! quote #(true) ] ; logic! --assert "" = try [make string! quote 1 ] ; integer! --assert "" = try [make string! quote 0 ] ; integer! --assert "" = try [make string! quote 4 ] ; integer! @@ -698,16 +698,16 @@ Rebol [ --assert "a/b" = try [make string! quote 'a/b ] ; lit-path! --assert "ref" = try [make string! quote /ref ] ; refinement! --assert "FF" = try [make string! quote #FF ] ; issue! - --assert "0 0" = try [make string! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert "a: 1" = try [make string! quote #[object! [a: 1]] ] ; object! - --assert "make bitset! #{FF}" = try [make string! quote #[bitset! #{FF}] ] ; bitset! - --assert "make image! [1x1 #{FFFFFF}]" = try [make string! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert "integer! percent!" = try [make string! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert "0 0" = try [make string! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert "a: 1" = try [make string! quote #(object! [a: 1]) ] ; object! + --assert "make bitset! #{FF}" = try [make string! quote #(bitset! #{FF}) ] ; bitset! + --assert "make image! [1x1 #{FFFFFF}]" = try [make string! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert "integer! percent!" = try [make string! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to string! ..." ;@@ https://github.com/Oldes/Rebol-issues/issues/1404 - --assert "" = try [to string! quote #[unset] ] ; unset! - --assert error? try [to string! quote #[none] ] ; none! - --assert "true" = try [to string! quote #[true] ] ; logic! + --assert "" = try [to string! quote #(unset) ] ; unset! + --assert error? try [to string! quote #(none) ] ; none! + --assert "true" = try [to string! quote #(true) ] ; logic! --assert "1" = try [to string! quote 1 ] ; integer! --assert "0" = try [to string! quote 0 ] ; integer! --assert "4" = try [to string! quote 4 ] ; integer! @@ -740,11 +740,11 @@ Rebol [ --assert "a/b" = try [to string! quote 'a/b ] ; lit-path! --assert "ref" = try [to string! quote /ref ] ; refinement! --assert "FF" = try [to string! quote #FF ] ; issue! - --assert "0 0" = try [to string! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert "a: 1" = try [to string! quote #[object! [a: 1]] ] ; object! - --assert "make bitset! #{FF}" = try [to string! quote #[bitset! #{FF}] ] ; bitset! - --assert "make image! [1x1 #{FFFFFF}]" = try [to string! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert "integer! percent!" = try [to string! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert "0 0" = try [to string! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert "a: 1" = try [to string! quote #(object! [a: 1]) ] ; object! + --assert "make bitset! #{FF}" = try [to string! quote #(bitset! #{FF}) ] ; bitset! + --assert "make image! [1x1 #{FFFFFF}]" = try [to string! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert "integer! percent!" = try [to string! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to string! with chars outside the BMP" ;; current Rebol is able to use only 16bit Unicode.. @@ -755,13 +755,13 @@ Rebol [ ===start-group=== "make/to tag" ;@@ https://github.com/Oldes/Rebol-issues/issues/1215 --test-- "make tag! .." - --assert #[tag! ""] = try [make tag! quote #[unset] ] ; unset! - --assert error? try [make tag! quote #[none] ] ; none! - --assert = try [make tag! quote #[true] ] ; logic! - --assert #[tag! ""] = try [make tag! quote 1 ] ; integer! - --assert #[tag! ""] = try [make tag! quote 0 ] ; integer! - --assert #[tag! ""] = try [make tag! quote 4 ] ; integer! - --assert #[tag! ""] = try [make tag! quote 4.0 ] ; decimal! + --assert #(tag! "") = try [make tag! quote #(unset) ] ; unset! + --assert error? try [make tag! quote #(none) ] ; none! + --assert = try [make tag! quote #(true) ] ; logic! + --assert #(tag! "") = try [make tag! quote 1 ] ; integer! + --assert #(tag! "") = try [make tag! quote 0 ] ; integer! + --assert #(tag! "") = try [make tag! quote 4 ] ; integer! + --assert #(tag! "") = try [make tag! quote 4.0 ] ; decimal! --assert <4%> = try [make tag! quote 4% ] ; percent! --assert <$4> = try [make tag! quote $4 ] ; money! --assert = try [make tag! quote #"a" ] ; char! @@ -769,13 +769,13 @@ Rebol [ --assert <1.1.1> = try [make tag! quote 1.1.1 ] ; tuple! --assert <10:00> = try [make tag! quote 10:00 ] ; time! --assert <1-Jan-2000> = try [make tag! quote 2000-01-01 ] ; date! - --assert #[tag! "^@"] = try [make tag! quote #{00} ] ; binary! + --assert #(tag! "^@") = try [make tag! quote #{00} ] ; binary! --assert <1 2> = try [make tag! quote #{312032} ] ; binary! - --assert #[tag! ""] = try [make tag! quote "" ] ; string! + --assert #(tag! "") = try [make tag! quote "" ] ; string! --assert <1 2> = try [make tag! quote "1 2" ] ; string! --assert = try [make tag! quote %file ] ; file! --assert = try [make tag! quote u@email ] ; email! - --assert = try [make tag! quote #[ref! "ref"] ] ; ref! + --assert = try [make tag! quote #(ref! "ref") ] ; ref! --assert = try [make tag! quote http://aa ] ; url! --assert = try [make tag! quote ] ; tag! --assert <12> = try [make tag! quote [1 2] ] ; block! @@ -786,15 +786,15 @@ Rebol [ --assert = try [make tag! quote 'a/b ] ; lit-path! --assert = try [make tag! quote /ref ] ; refinement! --assert = try [make tag! quote #FF ] ; issue! - --assert = try [make tag! quote #[bitset! #{FF}] ] ; bitset! - --assert = try [make tag! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert <0 0> = try [make tag! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert = try [make tag! quote #[object! [a: 1]] ] ; object! - --assert = try [make tag! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert = try [make tag! quote #(bitset! #{FF}) ] ; bitset! + --assert = try [make tag! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert <0 0> = try [make tag! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert = try [make tag! quote #(object! [a: 1]) ] ; object! + --assert = try [make tag! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to tag! .." - --assert #[tag! ""] = try [to tag! quote #[unset] ] ; unset! - --assert error? try [to tag! quote #[none] ] ; none! - --assert = try [to tag! quote #[true] ] ; logic! + --assert #(tag! "") = try [to tag! quote #(unset) ] ; unset! + --assert error? try [to tag! quote #(none) ] ; none! + --assert = try [to tag! quote #(true) ] ; logic! --assert <1> = try [to tag! quote 1 ] ; integer! --assert <0> = try [to tag! quote 0 ] ; integer! --assert <4> = try [to tag! quote 4 ] ; integer! @@ -806,13 +806,13 @@ Rebol [ --assert <1.1.1> = try [to tag! quote 1.1.1 ] ; tuple! --assert <10:00> = try [to tag! quote 10:00 ] ; time! --assert <1-Jan-2000> = try [to tag! quote 2000-01-01 ] ; date! - --assert #[tag! "^@"] = try [to tag! quote #{00} ] ; binary! + --assert #(tag! "^@") = try [to tag! quote #{00} ] ; binary! --assert <1 2> = try [to tag! quote #{312032} ] ; binary! - --assert #[tag! ""] = try [to tag! quote "" ] ; string! + --assert #(tag! "") = try [to tag! quote "" ] ; string! --assert <1 2> = try [to tag! quote "1 2" ] ; string! --assert = try [to tag! quote %file ] ; file! --assert = try [to tag! quote u@email ] ; email! - --assert = try [to tag! quote #[ref! "ref"] ] ; ref! + --assert = try [to tag! quote #(ref! "ref") ] ; ref! --assert = try [to tag! quote http://aa ] ; url! --assert = try [to tag! quote ] ; tag! --assert <12> = try [to tag! quote [1 2] ] ; block! @@ -823,19 +823,19 @@ Rebol [ --assert = try [to tag! quote 'a/b ] ; lit-path! --assert = try [to tag! quote /ref ] ; refinement! --assert = try [to tag! quote #FF ] ; issue! - --assert = try [to tag! quote #[bitset! #{FF}] ] ; bitset! - --assert = try [to tag! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert <0 0> = try [to tag! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert = try [to tag! quote #[object! [a: 1]] ] ; object! - --assert = try [to tag! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert = try [to tag! quote #(bitset! #{FF}) ] ; bitset! + --assert = try [to tag! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert <0 0> = try [to tag! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert = try [to tag! quote #(object! [a: 1]) ] ; object! + --assert = try [to tag! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== ===start-group=== "make/to typeset" ;@@ https://github.com/Oldes/Rebol-issues/issues/987 --test-- "make typeset! .." - --assert error? try [make typeset! quote #[unset] ] ; unset! - --assert error? try [make typeset! quote #[none] ] ; none! - --assert error? try [make typeset! quote #[true] ] ; logic! + --assert error? try [make typeset! quote #(unset) ] ; unset! + --assert error? try [make typeset! quote #(none) ] ; none! + --assert error? try [make typeset! quote #(true) ] ; logic! --assert error? try [make typeset! quote 1 ] ; integer! --assert error? try [make typeset! quote 0 ] ; integer! --assert error? try [make typeset! quote 4 ] ; integer! @@ -853,26 +853,26 @@ Rebol [ --assert error? try [make typeset! quote "1 2" ] ; string! --assert error? try [make typeset! quote %file ] ; file! --assert error? try [make typeset! quote u@email ] ; email! - --assert error? try [make typeset! quote #[ref! "ref"] ] ; ref! + --assert error? try [make typeset! quote #(ref! "ref") ] ; ref! --assert error? try [make typeset! quote http://aa ] ; url! --assert error? try [make typeset! quote ] ; tag! --assert error? try [make typeset! quote [1 2] ] ; block! - --assert #[typeset! [block!]] = make typeset! [block!] + --assert #(typeset! [block!]) = make typeset! [block!] --assert error? try [make typeset! quote (1 2) ] ; paren! --assert error? try [make typeset! quote a/b ] ; path! --assert error? try [make typeset! quote a/b: ] ; set-path! --assert error? try [make typeset! quote :a/b ] ; get-path! --assert error? try [make typeset! quote /ref ] ; refinement! --assert error? try [make typeset! quote #FF ] ; issue! - --assert error? try [make typeset! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make typeset! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [make typeset! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [make typeset! quote #[object! [a: 1]] ] ; object! - --assert #[typeset! [integer! percent!]] = try [make typeset! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make typeset! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make typeset! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [make typeset! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [make typeset! quote #(object! [a: 1]) ] ; object! + --assert #(typeset! [integer! percent!]) = try [make typeset! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to typeset! .." - --assert error? try [to typeset! quote #[unset] ] ; unset! - --assert error? try [to typeset! quote #[none] ] ; none! - --assert error? try [to typeset! quote #[true] ] ; logic! + --assert error? try [to typeset! quote #(unset) ] ; unset! + --assert error? try [to typeset! quote #(none) ] ; none! + --assert error? try [to typeset! quote #(true) ] ; logic! --assert error? try [to typeset! quote 1 ] ; integer! --assert error? try [to typeset! quote 0 ] ; integer! --assert error? try [to typeset! quote 4 ] ; integer! @@ -890,31 +890,31 @@ Rebol [ --assert error? try [to typeset! quote "1 2" ] ; string! --assert error? try [to typeset! quote %file ] ; file! --assert error? try [to typeset! quote u@email ] ; email! - --assert error? try [to typeset! quote #[ref! "ref"] ] ; ref! + --assert error? try [to typeset! quote #(ref! "ref") ] ; ref! --assert error? try [to typeset! quote http://aa ] ; url! --assert error? try [to typeset! quote ] ; tag! --assert error? try [to typeset! quote [1 2] ] ; block! - --assert #[typeset! [block!]] = to typeset! [block!] + --assert #(typeset! [block!]) = to typeset! [block!] --assert error? try [to typeset! quote (1 2) ] ; paren! --assert error? try [to typeset! quote a/b ] ; path! --assert error? try [to typeset! quote a/b: ] ; set-path! --assert error? try [to typeset! quote :a/b ] ; get-path! --assert error? try [to typeset! quote /ref ] ; refinement! --assert error? try [to typeset! quote #FF ] ; issue! - --assert error? try [to typeset! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [to typeset! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [to typeset! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [to typeset! quote #[object! [a: 1]] ] ; object! - --assert #[typeset! [integer! percent!]] = try [to typeset! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [to typeset! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [to typeset! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [to typeset! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [to typeset! quote #(object! [a: 1]) ] ; object! + --assert #(typeset! [integer! percent!]) = try [to typeset! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== ===start-group=== "make/to event" ;@@ https://github.com/Oldes/Rebol-issues/issues/986 --test-- "make event! .." --assert event? try [make event! make event! [type: 'connect]] - --assert error? try [make event! quote #[unset] ] ; unset! - --assert error? try [make event! quote #[none] ] ; none! - --assert error? try [make event! quote #[true] ] ; logic! + --assert error? try [make event! quote #(unset) ] ; unset! + --assert error? try [make event! quote #(none) ] ; none! + --assert error? try [make event! quote #(true) ] ; logic! --assert error? try [make event! quote 1 ] ; integer! --assert error? try [make event! quote 0 ] ; integer! --assert error? try [make event! quote 4 ] ; integer! @@ -932,7 +932,7 @@ Rebol [ --assert error? try [make event! quote "1 2" ] ; string! --assert error? try [make event! quote %file ] ; file! --assert error? try [make event! quote u@email ] ; email! - --assert error? try [make event! quote #[ref! "ref"] ] ; ref! + --assert error? try [make event! quote #(ref! "ref") ] ; ref! --assert error? try [make event! quote http://aa ] ; url! --assert error? try [make event! quote ] ; tag! --assert error? try [make event! quote [1 2] ] ; block! @@ -942,16 +942,16 @@ Rebol [ --assert error? try [make event! quote :a/b ] ; get-path! --assert error? try [make event! quote /ref ] ; refinement! --assert error? try [make event! quote #FF ] ; issue! - --assert error? try [make event! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make event! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [make event! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [make event! quote #[object! [a: 1]] ] ; object! - --assert error? try [make event! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make event! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make event! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [make event! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [make event! quote #(object! [a: 1]) ] ; object! + --assert error? try [make event! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to event! .." --assert event? try [to event! to event! [type: 'connect]] - --assert error? try [to event! quote #[unset] ] ; unset! - --assert error? try [to event! quote #[none] ] ; none! - --assert error? try [to event! quote #[true] ] ; logic! + --assert error? try [to event! quote #(unset) ] ; unset! + --assert error? try [to event! quote #(none) ] ; none! + --assert error? try [to event! quote #(true) ] ; logic! --assert error? try [to event! quote 1 ] ; integer! --assert error? try [to event! quote 0 ] ; integer! --assert error? try [to event! quote 4 ] ; integer! @@ -969,7 +969,7 @@ Rebol [ --assert error? try [to event! quote "1 2" ] ; string! --assert error? try [to event! quote %file ] ; file! --assert error? try [to event! quote u@email ] ; email! - --assert error? try [to event! quote #[ref! "ref"] ] ; ref! + --assert error? try [to event! quote #(ref! "ref") ] ; ref! --assert error? try [to event! quote http://aa ] ; url! --assert error? try [to event! quote ] ; tag! --assert error? try [to event! quote [1 2] ] ; block! @@ -979,20 +979,20 @@ Rebol [ --assert error? try [to event! quote :a/b ] ; get-path! --assert error? try [to event! quote /ref ] ; refinement! --assert error? try [to event! quote #FF ] ; issue! - --assert error? try [to event! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [to event! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [to event! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [to event! quote #[object! [a: 1]] ] ; object! - --assert error? try [to event! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [to event! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [to event! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [to event! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [to event! quote #(object! [a: 1]) ] ; object! + --assert error? try [to event! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== ===start-group=== "make/to word" ;@@ https://github.com/Oldes/Rebol-issues/issues/2492 --test-- "make word! ..." - --assert error? try [make word! quote #[unset] ] ; unset! - --assert error? try [make word! quote #[none] ] ; none! - --assert 'true = try [make word! quote #[true] ] ; logic! + --assert error? try [make word! quote #(unset) ] ; unset! + --assert error? try [make word! quote #(none) ] ; none! + --assert 'true = try [make word! quote #(true) ] ; logic! --assert error? try [make word! quote 1 ] ; integer! --assert error? try [make word! quote 0 ] ; integer! --assert error? try [make word! quote 4 ] ; integer! @@ -1011,7 +1011,7 @@ Rebol [ --assert 'file = try [make word! quote %file ] ; file! --assert error? try [make word! quote u@email ] ; email! --assert 'foo = try [make word! to email! "foo" ] ; email! - --assert 'ref = try [make word! quote #[ref! "ref"] ] ; ref! + --assert 'ref = try [make word! quote #(ref! "ref") ] ; ref! --assert error? try [make word! quote http://aa ] ; url! --assert 'foo = try [make word! to url! "foo" ] ; url --assert 'tag = try [make word! quote ] ; tag! @@ -1022,15 +1022,15 @@ Rebol [ --assert error? try [make word! quote :a/b ] ; get-path! --assert 'ref = try [make word! quote /ref ] ; refinement! --assert 'FF = try [make word! quote #FF ] ; issue! - --assert error? try [make word! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [make word! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [make word! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [make word! quote #[object! [a: 1]] ] ; object! - --assert error? try [make word! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [make word! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [make word! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [make word! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [make word! quote #(object! [a: 1]) ] ; object! + --assert error? try [make word! quote #(typeset! [integer! percent!]) ] ; typeset! --test-- "to word! ..." - --assert error? try [to word! quote #[unset] ] ; unset! - --assert error? try [to word! quote #[none] ] ; none! - --assert 'true = try [to word! quote #[true] ] ; logic! + --assert error? try [to word! quote #(unset) ] ; unset! + --assert error? try [to word! quote #(none) ] ; none! + --assert 'true = try [to word! quote #(true) ] ; logic! --assert error? try [to word! quote 1 ] ; integer! --assert error? try [to word! quote 0 ] ; integer! --assert error? try [to word! quote 4 ] ; integer! @@ -1049,7 +1049,7 @@ Rebol [ --assert 'file = try [to word! quote %file ] ; file! --assert error? try [to word! quote u@email ] ; email! --assert 'foo = try [to word! to email! "foo" ] ; email! - --assert 'ref = try [to word! quote #[ref! "ref"] ] ; ref! + --assert 'ref = try [to word! quote #(ref! "ref") ] ; ref! --assert error? try [to word! quote http://aa ] ; url! --assert 'foo = try [to word! to url! "foo" ] ; url --assert 'tag = try [to word! quote ] ; tag! @@ -1060,11 +1060,11 @@ Rebol [ --assert error? try [to word! quote :a/b ] ; get-path! --assert 'ref = try [to word! quote /ref ] ; refinement! --assert 'FF = try [to word! quote #FF ] ; issue! - --assert error? try [to word! quote #[bitset! #{FF}] ] ; bitset! - --assert error? try [to word! quote #[image! 1x1 #{FFFFFF}] ] ; image! - --assert error? try [to word! quote #[vector! integer! 32 2 [0 0]] ] ; vector! - --assert error? try [to word! quote #[object! [a: 1]] ] ; object! - --assert error? try [to word! quote #[typeset! [integer! percent!]] ] ; typeset! + --assert error? try [to word! quote #(bitset! #{FF}) ] ; bitset! + --assert error? try [to word! quote #(image! 1x1 #{FFFFFF}) ] ; image! + --assert error? try [to word! quote #(vector! integer! 32 2 [0 0]) ] ; vector! + --assert error? try [to word! quote #(object! [a: 1]) ] ; object! + --assert error? try [to word! quote #(typeset! [integer! percent!]) ] ; typeset! ===end-group=== @@ -1155,8 +1155,8 @@ Rebol [ --assert error? try [to bitset! none] --assert error? try [to image! none] --assert error? try [to vector! none] - --assert [#[none]] = try [to block! none] - --assert (quote (#[none])) = try [to paren! none] + --assert [#(none)] = try [to block! none] + --assert (quote (#(none))) = try [to paren! none] --assert path? try [to path! none] --assert set-path? try [to set-path! none] --assert get-path? try [to get-path! none] diff --git a/src/tests/units/map-test.r3 b/src/tests/units/map-test.r3 index 8b2f7703ff..e4c9085f44 100644 --- a/src/tests/units/map-test.r3 +++ b/src/tests/units/map-test.r3 @@ -19,25 +19,25 @@ Rebol [ --assert empty? make map! [] --test-- "#[map! []]" - m: #[map! [a: 1 b: 2]] + m: #(map! [a: 1 b: 2]) --assert 2 = m/b - --assert empty? #[map! []] + --assert empty? #(map! []) --test-- "#()" - m: #(a: 1 b: 2) + m: #[a: 1 b: 2] --assert 2 = m/b - --assert empty? #() + --assert empty? #[] --test-- "case sensitivity" ;@@ https://github.com/Oldes/Rebol-issues/issues/1153 - m: #( + m: #[ 1 2 3 4 %a 5 %A 6 %ab 7 %Ab 8 "a" 9 "A" 10 "ab" 11 "Ab" 12 a 13 A 14 ab 15 Ab 16 @a 17 @A 18 @ab 19 @Ab 20 #"a" 21 #"A" 22 #{61} 23 #{41} 24 - ) + ] --assert 24 = length? m --assert 1 = select m --assert 5 = select m %A @@ -102,14 +102,14 @@ Rebol [ ===start-group=== "find" --test-- "map-find-1" - mf1-m: #(a: none b: 1 c: 2) + mf1-m: #[a: none b: 1 c: 2] --assert 'a = find mf1-m 'a --assert 'b = find mf1-m 'b --assert 'c = find mf1-m 'c --assert none = find mf1-m 'd --test-- "map-find-2" - mf2-m: #(a: 1 b: 2 c: 3) + mf2-m: #[a: 1 b: 2 c: 3] mf2-m/a: 'none mf2-m/b: none --assert 'a = find mf2-m 'a @@ -117,7 +117,7 @@ Rebol [ --assert 'c = find mf2-m 'c --test-- "map-find-3" - mf3-m: #(aB: 1 ab: 2 AB: 3) + mf3-m: #[aB: 1 ab: 2 AB: 3] --assert 'ab = find/case mf3-m 'ab --assert none = find/case mf3-m 'Ab @@ -207,7 +207,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/1864 --test-- "copy/deep map" - m1: #(b: [1]) + m1: #[b: [1]] m2: copy m1 m3: copy/deep m1 --assert same? m1/b m2/b @@ -242,24 +242,24 @@ Rebol [ ===start-group=== "FORM map!" --test-- "form empty map" - --assert "" = form #() + --assert "" = form #[] --test-- "form single key map" - --assert "a: 1" = form #(a: 1) + --assert "a: 1" = form #[a: 1] --test-- "form map with multiple keys" - --assert "a: 1^/b: 2" = form #(a: 1 b: 2) ; there should not be line break at tail + --assert "a: 1^/b: 2" = form #[a: 1 b: 2] ; there should not be line break at tail ===end-group=== ===start-group=== "PUT" --test-- "PUT into map" - m: #(a: 42) + m: #[a: 42] --assert "foo" = put m 'b "foo" --assert "baz" = put m 'a "baz" --assert "foo" = m/b --assert "baz" = m/a --test-- "PUT into protected map" - m: #(a: 42) + m: #[a: 42] protect m --assert error? err: try [put m 'b "foo"] --assert err/id = 'protected @@ -289,7 +289,7 @@ Rebol [ --test-- "spec of map" ;@@ https://github.com/Oldes/Rebol-issues/issues/1859 --assert all [ - error? e: try [ spec-of #() ] + error? e: try [ spec-of #[] ] e/id = 'expect-arg e/arg2 = 'value e/arg3 = map! @@ -304,7 +304,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-wishes/issues/31 --assert {a: 1^/b: 2^/c: 3^/d: 4^/e: 5^/f: 6^/"a" 7^/ 8^/9 9^/#"c" 10^/a@b 11^/3.14 12^/1x0 13^/$1 14} = mold/only to block! m - --assert {[^/ a: 1^/ b: 2^/]} = mold to block! #(a: 1 b: 2) + --assert {[^/ a: 1^/ b: 2^/]} = mold to block! #[a: 1 b: 2] --test-- "more keys.." ;@@ https://github.com/Oldes/Rebol-issues/issues/1804 @@ -316,10 +316,10 @@ Rebol [ ===start-group=== "MAP with NONE" ;@@ https://github.com/Oldes/Rebol-wishes/issues/21 --test-- "map with none" - m: #(a: #[none] b: 1) + m: #[a: #(none) b: 1] m/b: none --assert [a b] = keys-of m - --assert [#[none] #[none]] = values-of m + --assert [#(none) #(none)] = values-of m --test-- "foreach on map with none" o: copy "" foreach [k v] m [append o k] @@ -327,12 +327,12 @@ Rebol [ --test-- "remove from map" ;@@ https://github.com/Oldes/Rebol-wishes/issues/20 - m: #("ab" 1 "AB" 2) + m: #["ab" 1 "AB" 2] --assert ["ab" 1 "AB" 2] = to block! remove/key m "aB" --assert 2 = length? m --assert ["ab" 1 ] = to block! remove/key m "AB" --assert 1 = length? m - m: #(ab: 1 AB: 2) + m: #[ab: 1 AB: 2] --assert [ab: 1 AB: 2] = to block! remove/key m 'aB --assert 2 = length? m --assert [ab: 1 ] = to block! remove/key m 'AB @@ -344,11 +344,11 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/806 ;@@ https://github.com/red/REP/issues/93 --test-- "remove-each with map" - m: #(a 1 "b" 2 c #[none] d: 3) + m: #[a 1 "b" 2 c #(none) d: 3] --assert m = remove-each [k v] m [any [string? k none? v]] --assert [a d] = words-of m --test-- "remove-each/count with map" - m: #(a 1 "b" 2 c #[none] d: 3) + m: #[a 1 "b" 2 c #(none) d: 3] --assert 2 = remove-each/count [k v] m [any [string? k none? v]] --assert [a d] = words-of m @@ -357,55 +357,55 @@ Rebol [ ===start-group=== "set operations with map!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1984 - m1: #(a: 1 A: 2 "b" 3 "B" 4) - m2: #(a: 2 c: 5 "b" 6 "D" 7) + m1: #[a: 1 A: 2 "b" 3 "B" 4] + m2: #[a: 2 c: 5 "b" 6 "D" 7] --test-- "difference with map" - --assert (mold/flat difference m1 m1) = {#()} - --assert (mold/flat difference m1 m2) = {#(c: 5 "D" 7)} - --assert (mold/flat difference m2 m1) = {#(c: 5 "D" 7)} - --assert (mold/flat difference m2 m2) = {#()} + --assert (mold/flat difference m1 m1) = {#[]} + --assert (mold/flat difference m1 m2) = {#[c: 5 "D" 7]} + --assert (mold/flat difference m2 m1) = {#[c: 5 "D" 7]} + --assert (mold/flat difference m2 m2) = {#[]} - --assert (mold/flat difference/case m1 m1) = {#()} - --assert (mold/flat difference/case m1 m2) = {#(A: 2 "B" 4 c: 5 "D" 7)} - --assert (mold/flat difference/case m2 m1) = {#(c: 5 "D" 7 A: 2 "B" 4)} - --assert (mold/flat difference/case m2 m2) = {#()} + --assert (mold/flat difference/case m1 m1) = {#[]} + --assert (mold/flat difference/case m1 m2) = {#[A: 2 "B" 4 c: 5 "D" 7]} + --assert (mold/flat difference/case m2 m1) = {#[c: 5 "D" 7 A: 2 "B" 4]} + --assert (mold/flat difference/case m2 m2) = {#[]} --test-- "exclude with map" - --assert (mold/flat exclude m1 m1) = {#()} - --assert (mold/flat exclude m1 m2) = {#()} - --assert (mold/flat exclude m2 m1) = {#(c: 5 "D" 7)} - --assert (mold/flat exclude m2 m2) = {#()} + --assert (mold/flat exclude m1 m1) = {#[]} + --assert (mold/flat exclude m1 m2) = {#[]} + --assert (mold/flat exclude m2 m1) = {#[c: 5 "D" 7]} + --assert (mold/flat exclude m2 m2) = {#[]} - --assert (mold/flat exclude/case m1 m1) = {#()} - --assert (mold/flat exclude/case m1 m2) = {#(A: 2 "B" 4)} - --assert (mold/flat exclude/case m2 m1) = {#(c: 5 "D" 7)} - --assert (mold/flat exclude/case m2 m2) = {#()} + --assert (mold/flat exclude/case m1 m1) = {#[]} + --assert (mold/flat exclude/case m1 m2) = {#[A: 2 "B" 4]} + --assert (mold/flat exclude/case m2 m1) = {#[c: 5 "D" 7]} + --assert (mold/flat exclude/case m2 m2) = {#[]} --test-- "intersect with map" - --assert (mold/flat intersect m1 m1) = {#(a: 1 "b" 3)} - --assert (mold/flat intersect m1 m2) = {#(a: 1 "b" 3)} - --assert (mold/flat intersect m2 m1) = {#(a: 2 "b" 6)} - --assert (mold/flat intersect m2 m2) = {#(a: 2 c: 5 "b" 6 "D" 7)} + --assert (mold/flat intersect m1 m1) = {#[a: 1 "b" 3]} + --assert (mold/flat intersect m1 m2) = {#[a: 1 "b" 3]} + --assert (mold/flat intersect m2 m1) = {#[a: 2 "b" 6]} + --assert (mold/flat intersect m2 m2) = {#[a: 2 c: 5 "b" 6 "D" 7]} - --assert (mold/flat intersect/case m1 m1) = {#(a: 1 A: 2 "b" 3 "B" 4)} - --assert (mold/flat intersect/case m1 m2) = {#(a: 1 "b" 3)} - --assert (mold/flat intersect/case m2 m1) = {#(a: 2 "b" 6)} - --assert (mold/flat intersect/case m2 m2) = {#(a: 2 c: 5 "b" 6 "D" 7)} + --assert (mold/flat intersect/case m1 m1) = {#[a: 1 A: 2 "b" 3 "B" 4]} + --assert (mold/flat intersect/case m1 m2) = {#[a: 1 "b" 3]} + --assert (mold/flat intersect/case m2 m1) = {#[a: 2 "b" 6]} + --assert (mold/flat intersect/case m2 m2) = {#[a: 2 c: 5 "b" 6 "D" 7]} --test-- "union with map" - --assert (mold/flat union m1 m1) = {#(a: 1 "b" 3)} - --assert (mold/flat union m1 m2) = {#(a: 1 "b" 3 c: 5 "D" 7)} - --assert (mold/flat union m2 m1) = {#(a: 2 c: 5 "b" 6 "D" 7)} - --assert (mold/flat union m2 m2) = {#(a: 2 c: 5 "b" 6 "D" 7)} + --assert (mold/flat union m1 m1) = {#[a: 1 "b" 3]} + --assert (mold/flat union m1 m2) = {#[a: 1 "b" 3 c: 5 "D" 7]} + --assert (mold/flat union m2 m1) = {#[a: 2 c: 5 "b" 6 "D" 7]} + --assert (mold/flat union m2 m2) = {#[a: 2 c: 5 "b" 6 "D" 7]} - --assert (mold/flat union/case m1 m1) = {#(a: 1 A: 2 "b" 3 "B" 4)} - --assert (mold/flat union/case m1 m2) = {#(a: 1 A: 2 "b" 3 "B" 4 c: 5 "D" 7)} - --assert (mold/flat union/case m2 m1) = {#(a: 2 c: 5 "b" 6 "D" 7 A: 2 "B" 4)} - --assert (mold/flat union/case m2 m2) = {#(a: 2 c: 5 "b" 6 "D" 7)} + --assert (mold/flat union/case m1 m1) = {#[a: 1 A: 2 "b" 3 "B" 4]} + --assert (mold/flat union/case m1 m2) = {#[a: 1 A: 2 "b" 3 "B" 4 c: 5 "D" 7]} + --assert (mold/flat union/case m2 m1) = {#[a: 2 c: 5 "b" 6 "D" 7 A: 2 "B" 4]} + --assert (mold/flat union/case m2 m2) = {#[a: 2 c: 5 "b" 6 "D" 7]} --test-- "unique with map" - --assert (mold/flat unique m1) = {#(a: 1 "b" 3)} - --assert (mold/flat unique/case m1) = {#(a: 1 A: 2 "b" 3 "B" 4)} + --assert (mold/flat unique m1) = {#[a: 1 "b" 3]} + --assert (mold/flat unique/case m1) = {#[a: 1 A: 2 "b" 3 "B" 4]} ===end-group=== diff --git a/src/tests/units/module-test.r3 b/src/tests/units/module-test.r3 index 135654e598..3928c8da7e 100644 --- a/src/tests/units/module-test.r3 +++ b/src/tests/units/module-test.r3 @@ -151,7 +151,7 @@ system/options/modules: join what-dir %units/files/ --test-- "make module! map!" ; not allowed ;@@ https://github.com/Oldes/Rebol-issues/issues/1551 --assert all [ - error? err: try [make module! #(a: 1)] + error? err: try [make module! #[a: 1]] err/id = 'bad-make-arg ] --test-- "make module! object!" ; not allowed @@ -394,13 +394,13 @@ probe all [ --test-- "issue-1005" ;@@ https://github.com/Oldes/Rebol-issues/issues/1005 m: module [] [a: 1 2] - --assert [lib-local: #[object![]] a: 1] = body-of m + --assert [lib-local: #(object![]) a: 1] = body-of m --assert [lib-local a] = keys-of m - --assert [#[object![]] 1] = values-of m + --assert [#(object![]) 1] = values-of m m: module [exports: [a]] [a: 1 2] - --assert [lib-local: #[object![]] a: 1] = body-of m + --assert [lib-local: #(object![]) a: 1] = body-of m --assert [lib-local a] = keys-of m - --assert [#[object![]] 1] = values-of m + --assert [#(object![]) 1] = values-of m --test-- "issue-1708" ;@@ https://github.com/Oldes/Rebol-issues/issues/1708 diff --git a/src/tests/units/mold-test.r3 b/src/tests/units/mold-test.r3 index 31d4c349c9..47e7bf7cb2 100644 --- a/src/tests/units/mold-test.r3 +++ b/src/tests/units/mold-test.r3 @@ -266,25 +266,25 @@ Rebol [ --test-- "mold-true" --assert "true" = mold true - --test-- "mold-all-true" --assert "#[true]" = mold/all true + --test-- "mold-all-true" --assert "#(true)" = mold/all true --test-- "mold-false" --assert "false" = mold false - --test-- "mold-all-false" --assert "#[false]" = mold/all false + --test-- "mold-all-false" --assert "#(false)" = mold/all false --test-- "mold-none" --assert "none" = mold none - --test-- "mold-all-none" --assert "#[none]" = mold/all none + --test-- "mold-all-none" --assert "#(none)" = mold/all none - --test-- "mold-block" --assert "[true false none]" = mold [#[true] #[false] #[none]] + --test-- "mold-block" --assert "[true false none]" = mold [#(true) #(false) #(none)] --test-- "mold-all-block" - --assert "[#[true] #[false] #[none]]" = mold/all [#[true] #[false] #[none]] + --assert "[#(true) #(false) #(none)]" = mold/all [#(true) #(false) #(none)] --test-- "mold/all block at tail" ;@@ https://github.com/Oldes/Rebol-issues/issues/1192 - --assert "#[path! [p p] 3]" = mold/all next next 'p/p - --assert "#[block! [a b] 3]" = mold/all next next [a b] + --assert "#(path! [p p] 3)" = mold/all next next 'p/p + --assert "#(block! [a b] 3)" = mold/all next next [a b] ===end-group=== @@ -348,7 +348,7 @@ Rebol [ --test-- "mold/flat/all block!" --assert (mold/flat/all c) = {["A" [1 2 3 4]]} - --assert (mold/flat/all next c) = {#[block! ["A" [1 2 3 4]] 2]} + --assert (mold/flat/all next c) = {#(block! ["A" [1 2 3 4]] 2)} --test-- "mold/only" ;@@ https://github.com/Oldes/Rebol-issues/issues/732 @@ -384,27 +384,27 @@ Rebol [ ] ] - --assert (mold m) = {#( + --assert (mold m) = {#[ a: 1 b: 2 c: [ 3 4 ] -)} +]} --test-- "mold/flat map!" ;@@ https://github.com/Oldes/Rebol-issues/issues/2401 - --assert "#(a: 1 b: 2 c: [3 4])" = mold/flat m - --assert "#[map! [a: 1 b: 2 c: [3 4]]]" = mold/flat/all m + --assert "#[a: 1 b: 2 c: [3 4]]" = mold/flat m + --assert "#(map! [a: 1 b: 2 c: [3 4]])" = mold/flat/all m --test-- "mold with recursive value" m/c: m - --assert "#(a: 1 b: 2 c: #(...))" = mold/flat m + --assert "#[a: 1 b: 2 c: #[...]]" = mold/flat m - --test-- "mold #()" + --test-- "mold #[]" ;@@ https://github.com/Oldes/Rebol-issues/issues/725 - --assert "#()" = mold #() - --assert "#[map! []]" = mold/all #() + --assert "#[]" = mold #[] + --assert "#(map! [])" = mold/all #[] ===end-group=== @@ -461,8 +461,8 @@ Rebol [ --assert "@name" = mold @name --assert "@ame" = mold next @name --assert "@šiška" = mold @šiška - --assert {#[ref! "a@"]} = mold to ref! "a@" - --assert {#[ref! "a^^/b"]} = mold append @a "^/b" + --assert {#(ref! "a@")} = mold to ref! "a@" + --assert {#(ref! "a^^/b")} = mold append @a "^/b" --test-- "form ref" --assert "name" = form @name --assert "ame" = form next @name @@ -490,13 +490,13 @@ Rebol [ --assert (mold/flat make image! [1x1 0.0.0.66]) = {make image! [1x1 #{000000} #{42}]} --test-- "mold/flat/all image!" - --assert (mold/all/flat make image! 8x1) = {#[image! 8x1 #{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}]} - --assert (mold/all/flat next make image! 8x1) = {#[image! 8x1 #{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF} 2]} + --assert (mold/all/flat make image! 8x1) = {#(image! 8x1 #{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF})} + --assert (mold/all/flat next make image! 8x1) = {#(image! 8x1 #{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF} 2)} --test-- "mold/part image!" img: make image! 2 * 1920x1080 --assert "make image! [3840x2160 #{FFFFF" = mold/part img 30 - --assert "#[image! 3840x2160 #{FFFFFFFFF" = mold/part/all img 30 + --assert "#(image! 3840x2160 #{FFFFFFFFF" = mold/part/all img 30 ===end-group=== @@ -516,7 +516,7 @@ Rebol [ --test-- "mold/all gob!" ;@@ https://github.com/Oldes/Rebol-issues/issues/989 - --assert "#[gob! [offset: 0x0 size: 100x100]]" = mold/all make gob! [] + --assert "#(gob! [offset: 0x0 size: 100x100])" = mold/all make gob! [] ===end-group=== @@ -524,10 +524,10 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/567 ;@@ https://github.com/Oldes/Rebol-issues/issues/2508 --test-- "mold unset!" - --assert "#[unset]" = mold () - --assert "#[unset]" = mold/all () + --assert "#(unset)" = mold () + --assert "#(unset)" = mold/all () --assert "unset!" = mold type? () - --assert "#[unset!]" = mold/all type? () + --assert "#(unset!)" = mold/all type? () --test-- "form unset!" --assert "" = form () @@ -537,10 +537,10 @@ Rebol [ --test-- "mold path" --assert "a/b" = mold 'a/b --assert "b" = mold next 'a/b - --assert "#[path! [a b] 2]" = mold/all next 'a/b + --assert "#(path! [a b] 2)" = mold/all next 'a/b --test-- "mold empty path" ;@@ https://github.com/Oldes/Rebol-issues/issues/868 - --assert "#[path! []]" = mold make path! [] + --assert "#(path! [])" = mold make path! [] ===end-group=== @@ -548,7 +548,7 @@ Rebol [ ===start-group=== "mold/all" --test-- "mold/all datatype!" ;@@ https://github.com/Oldes/Rebol-issues/issues/219 - --assert "#[integer!]" = mold/all integer! + --assert "#(integer!)" = mold/all integer! --test-- "mold/all decimal!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1633 @@ -558,7 +558,7 @@ Rebol [ --test-- "mold/all typeset!" ;@@ https://github.com/Oldes/Rebol-issues/issues/2510 --assert "make typeset! [integer! decimal! percent!]" = mold number! - --assert "#[typeset! [integer! decimal! percent!]]" = mold/all number! + --assert "#(typeset! [integer! decimal! percent!])" = mold/all number! ===end-group=== @@ -577,8 +577,8 @@ Rebol [ --test-- "mold error!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1003 --assert {make error! [code: 101 type: 'Note id: 'exited arg1: none arg2: none arg3: none near: none where: none]} = mold/flat make error! [type: 'Note id: 'exited] - --assert {#[error! [code: 101 type: Note id: exited arg1: #[none] arg2: #[none] arg3: #[none] near: #[none] where: #[none]]]} = mold/all/flat make error! [type: 'Note id: 'exited] - --assert {#[error! [code: 401 type: Math id: overflow arg1: #[none] arg2: #[none] arg3: #[none] near: #[none] where: #[none]]]} = mold/all/flat make error! [type: 'Math id: 'overflow] + --assert {#(error! [code: 101 type: Note id: exited arg1: #(none) arg2: #(none) arg3: #(none) near: #(none) where: #(none)])} = mold/all/flat make error! [type: 'Note id: 'exited] + --assert {#(error! [code: 401 type: Math id: overflow arg1: #(none) arg2: #(none) arg3: #(none) near: #(none) where: #(none)])} = mold/all/flat make error! [type: 'Math id: 'overflow] ===end-group=== diff --git a/src/tests/units/object-test.r3 b/src/tests/units/object-test.r3 index af250bd719..71d69e346d 100644 --- a/src/tests/units/object-test.r3 +++ b/src/tests/units/object-test.r3 @@ -50,17 +50,17 @@ Rebol [ --assert 2 = obj/a --assert 3 = put obj 'b 3 --assert 3 = obj/b - --assert unset? put obj 'b #[unset] + --assert unset? put obj 'b #(unset) --assert unset? obj/b --test-- "compare extended objects" ;@@ https://github.com/Oldes/Rebol-issues/issues/2507 - --assert equal? #[object! [a: 1]] #[object! [a: 1]] - --assert equal? #[object! [a: 1]] make object! [a: 1] - put obj: #[object! []] 'a 1 - --assert equal? obj #[object! [a: 1]] - append obj: #[object! []] [a 1] - --assert equal? obj #[object! [a: 1]] + --assert equal? #(object! [a: 1]) #(object! [a: 1]) + --assert equal? #(object! [a: 1]) make object! [a: 1] + put obj: #(object! []) 'a 1 + --assert equal? obj #(object! [a: 1]) + append obj: #(object! []) [a 1] + --assert equal? obj #(object! [a: 1]) --test-- "extend object" obj: object [] @@ -317,10 +317,10 @@ Rebol [ --test-- "empty?" ;@@ https://github.com/Oldes/Rebol-issues/issues/1669 --assert empty? object [] - --assert empty? #[object! []] + --assert empty? #(object! []) --test-- "length?" --assert 0 = length? object [] - --assert 0 = length? #[object! []] + --assert 0 = length? #(object! []) ===end-group=== diff --git a/src/tests/units/parse-test.r3 b/src/tests/units/parse-test.r3 index 2eca5c046f..86e5cd2471 100644 --- a/src/tests/units/parse-test.r3 +++ b/src/tests/units/parse-test.r3 @@ -222,9 +222,9 @@ Rebol [ --assert [3 "A"] = parse [1][collect [integer! keep (1 + 2) keep ("A")]] --test-- "block collect set" - a: none --assert all [#[true] = parse [ ] [collect set a []] a = []] - a: none --assert all [#[true] = parse [1] [collect set a [keep skip]] a = [1]] - a: none --assert all [#[false] = parse [1 2] [collect set a [keep skip]] a = [1]] + a: none --assert all [#(true) = parse [ ] [collect set a []] a = []] + a: none --assert all [#(true) = parse [1] [collect set a [keep skip]] a = [1]] + a: none --assert all [#(false) = parse [1 2] [collect set a [keep skip]] a = [1]] a: none --assert all [ [] = parse [1] [collect [collect set a keep skip]] a = [1] @@ -238,11 +238,11 @@ Rebol [ a = 1 ] a: none --assert all [ - #[true] = parse [1] [collect set a [collect set a keep skip]] + #(true) = parse [1] [collect set a [collect set a keep skip]] a = [1] ] a: b: none --assert all [ - #[true] = parse [1] [collect set a [collect set b keep skip]] + #(true) = parse [1] [collect set a [collect set b keep skip]] a = [] b = [1] ] @@ -308,9 +308,9 @@ Rebol [ --assert [1 2] = parse #{0102} [collect [keep pick 2 skip]] --test-- "string collect set" - a: none --assert all [#[true] = parse "" [collect set a []] a = []] - a: none --assert all [#[true] = parse "1" [collect set a [keep skip]] a = [#"1"]] - a: none --assert all [#[false] = parse "12" [collect set a [keep skip]] a = [#"1"]] + a: none --assert all [#(true) = parse "" [collect set a []] a = []] + a: none --assert all [#(true) = parse "1" [collect set a [keep skip]] a = [#"1"]] + a: none --assert all [#(false) = parse "12" [collect set a [keep skip]] a = [#"1"]] a: none --assert all [ [] = parse "1" [collect [collect set a keep skip]] a = [#"1"] @@ -324,11 +324,11 @@ Rebol [ a = #"1" ] a: none --assert all [ - #[true] = parse "1" [collect set a [collect set a keep skip]] + #(true) = parse "1" [collect set a [collect set a keep skip]] a = [#"1"] ] a: b: none --assert all [ - #[true] = parse "1" [collect set a [collect set b keep skip]] + #(true) = parse "1" [collect set a [collect set b keep skip]] a = [] b = [#"1"] ] @@ -404,7 +404,7 @@ Rebol [ --assert all [ alpha: system/catalog/bitsets/alpha numer: system/catalog/bitsets/numeric - #[true] = parse "11ab2c33" [ + #(true) = parse "11ab2c33" [ collect set res [ keep (quote alpha: ) collect [some [keep some alpha | skip] fail] | keep (quote numeric:) collect [some [keep some numer | skip]] diff --git a/src/tests/units/rsa-test.r3 b/src/tests/units/rsa-test.r3 index 85b02629a1..ba98bba00c 100644 --- a/src/tests/units/rsa-test.r3 +++ b/src/tests/units/rsa-test.r3 @@ -67,8 +67,8 @@ Rebol [ --test-- "Init RSA keys" --assert handle? key-pub: rsa-init ko/n ko/e ;<-- this key has only public properties --assert handle? key-pri: rsa-init/private ko/n ko/e ko/d ko/p ko/q ;ko/dp ko/dq ko/qp - --assert "#[handle! rsa]" = mold key-pub - --assert "#[handle! rsa]" = mold key-pri + --assert "#(handle! rsa)" = mold key-pub + --assert "#(handle! rsa)" = mold key-pri ;@@ https://github.com/Oldes/Rebol-issues/issues/906 --assert [type] = words-of key-pri --assert 'rsa = query/mode key-pri 'type diff --git a/src/tests/units/series-test.r3 b/src/tests/units/series-test.r3 index 45ddaa0f44..b540c7e764 100644 --- a/src/tests/units/series-test.r3 +++ b/src/tests/units/series-test.r3 @@ -23,9 +23,9 @@ Rebol [ --assert "anone" == join "a" none --assert %anone == join %a none --assert "anone" == join #"a" none - --assert error? try [join "a" #[unset]] - --assert error? try [join %a #[unset]] - --assert error? try [join #"a" #[unset]] + --assert error? try [join "a" #(unset)] + --assert error? try [join %a #(unset)] + --assert error? try [join #"a" #(unset)] ;@@ https://github.com/Oldes/Rebol-issues/issues/2558 --test-- "AJOIN" @@ -34,16 +34,16 @@ Rebol [ --assert %ab3 == ajoin [ %a "b" 3] --assert "ab3" == ajoin [#"a" "b" 3] --assert "b3" == ajoin [ "b" 3] ;; by design not a tag! - --assert "a3" == ajoin [ "a" #[none] 3] - --assert %a3 == ajoin [ %a #[none] 3] - --assert "a3" == ajoin [#"a" #[none] 3] - --assert "a3" == ajoin [ "a" #[unset] 3] - --assert %a3 == ajoin [ %a #[unset] 3] - --assert "a3" == ajoin [#"a" #[unset] 3] + --assert "a3" == ajoin [ "a" #(none) 3] + --assert %a3 == ajoin [ %a #(none) 3] + --assert "a3" == ajoin [#"a" #(none) 3] + --assert "a3" == ajoin [ "a" #(unset) 3] + --assert %a3 == ajoin [ %a #(unset) 3] + --assert "a3" == ajoin [#"a" #(unset) 3] ;; when first value is not a string, result is always string - --assert "a3" == ajoin [#[none] "a" 3] - --assert "a3" == ajoin [#[none] %a 3] - --assert "a3" == ajoin [#[none] #"a" 3] + --assert "a3" == ajoin [#(none) "a" 3] + --assert "a3" == ajoin [#(none) %a 3] + --assert "a3" == ajoin [#(none) #"a" 3] ;; nested ajoin --assert "1234" == ajoin [1 2 ajoin [3 4]] @@ -52,16 +52,16 @@ Rebol [ --assert "ab3" == ajoin/all [ "a" "b" 3] --assert %ab3 == ajoin/all [ %a "b" 3] --assert "ab3" == ajoin/all [#"a" "b" 3] - --assert "anone3" == ajoin/all [ "a" #[none] 3] - --assert %anone3 == ajoin/all [ %a #[none] 3] - --assert "anone3" == ajoin/all [#"a" #[none] 3] - --assert "a3" == ajoin/all [ "a" #[unset] 3] - --assert %a3 == ajoin/all [ %a #[unset] 3] - --assert "a3" == ajoin/all [#"a" #[unset] 3] + --assert "anone3" == ajoin/all [ "a" #(none) 3] + --assert %anone3 == ajoin/all [ %a #(none) 3] + --assert "anone3" == ajoin/all [#"a" #(none) 3] + --assert "a3" == ajoin/all [ "a" #(unset) 3] + --assert %a3 == ajoin/all [ %a #(unset) 3] + --assert "a3" == ajoin/all [#"a" #(unset) 3] ;; when first value is not a string, result is always string - --assert "nonea3" == ajoin/all [#[none] "a" 3] - --assert "nonea3" == ajoin/all [#[none] %a 3] - --assert "nonea3" == ajoin/all [#[none] #"a" 3] + --assert "nonea3" == ajoin/all [#(none) "a" 3] + --assert "nonea3" == ajoin/all [#(none) %a 3] + --assert "nonea3" == ajoin/all [#(none) #"a" 3] --test-- "AJOIN/with" --assert "a/b/3" == ajoin/with [ 'a 'b 3] #"/" @@ -69,24 +69,24 @@ Rebol [ --assert %a/b/3 == ajoin/with [ %a "b" 3] #"/" --assert "a/b/3" == ajoin/with [#"a" "b" 3] #"/" --assert "/b/3" == ajoin/with [ "b" 3] #"/" ;; by design not a tag! - --assert "a/3" == ajoin/with [ "a" #[none] 3] #"/" - --assert %a/3 == ajoin/with [ %a #[none] 3] #"/" - --assert "a/3" == ajoin/with [#"a" #[none] 3] #"/" - --assert "a/3" == ajoin/with [ "a" #[unset] 3] #"/" - --assert %a/3 == ajoin/with [ %a #[unset] 3] #"/" - --assert "a/3" == ajoin/with [#"a" #[unset] 3] #"/" + --assert "a/3" == ajoin/with [ "a" #(none) 3] #"/" + --assert %a/3 == ajoin/with [ %a #(none) 3] #"/" + --assert "a/3" == ajoin/with [#"a" #(none) 3] #"/" + --assert "a/3" == ajoin/with [ "a" #(unset) 3] #"/" + --assert %a/3 == ajoin/with [ %a #(unset) 3] #"/" + --assert "a/3" == ajoin/with [#"a" #(unset) 3] #"/" --test-- "AJOIN/all/with" --assert "a/b/3" == ajoin/all/with [ 'a 'b 3] #"/" --assert "a/b/3" == ajoin/all/with [ "a" "b" 3] #"/" --assert %a/b/3 == ajoin/all/with [ %a "b" 3] #"/" --assert "a/b/3" == ajoin/all/with [#"a" "b" 3] #"/" - --assert "a/none/3" == ajoin/all/with [ "a" #[none] 3] #"/" - --assert %a/none/3 == ajoin/all/with [ %a #[none] 3] #"/" - --assert "a/none/3" == ajoin/all/with [#"a" #[none] 3] #"/" - --assert "a//3" == ajoin/all/with [ "a" #[unset] 3] #"/" - --assert %a//3 == ajoin/all/with [ %a #[unset] 3] #"/" - --assert "a//3" == ajoin/all/with [#"a" #[unset] 3] #"/" + --assert "a/none/3" == ajoin/all/with [ "a" #(none) 3] #"/" + --assert %a/none/3 == ajoin/all/with [ %a #(none) 3] #"/" + --assert "a/none/3" == ajoin/all/with [#"a" #(none) 3] #"/" + --assert "a//3" == ajoin/all/with [ "a" #(unset) 3] #"/" + --assert %a//3 == ajoin/all/with [ %a #(unset) 3] #"/" + --assert "a//3" == ajoin/all/with [#"a" #(unset) 3] #"/" --test-- "FORM" --assert "a b 3" == form [ 'a 'b 3] @@ -94,15 +94,15 @@ Rebol [ --assert "a b 3" == form [ %a "b" 3] --assert "a b 3" == form [#"a" "b" 3] --assert " b 3" == form [ "b" 3] - --assert "a none 3" == form [ "a" #[none] 3] - --assert "a none 3" == form [ %a #[none] 3] - --assert "a none 3" == form [#"a" #[none] 3] - --assert "a 3" == form [ "a" #[unset] 3] - --assert "a 3" == form [ %a #[unset] 3] - --assert "a 3" == form [#"a" #[unset] 3] + --assert "a none 3" == form [ "a" #(none) 3] + --assert "a none 3" == form [ %a #(none) 3] + --assert "a none 3" == form [#"a" #(none) 3] + --assert "a 3" == form [ "a" #(unset) 3] + --assert "a 3" == form [ %a #(unset) 3] + --assert "a 3" == form [#"a" #(unset) 3] ;@@ https://github.com/Oldes/Rebol-issues/issues/2560 --assert " 1 2" == form ["" "" 1 "" 2] - --assert " 1 2" == form [#[unset] #[unset] 1 #[unset] 2] + --assert " 1 2" == form [#(unset) #(unset) 1 #(unset) 2] ===end-group=== @@ -494,12 +494,12 @@ Rebol [ --assert #{00110000} = head trim/head at copy bin 2 --assert #{0011} = head trim/all at copy bin 2 --test-- "trim block!" - blk: [#[none] 1 #[none] 2 #[none]] + blk: [#(none) 1 #(none) 2 #(none)] ;@@ https://github.com/Oldes/Rebol-issues/issues/825 - --assert [1 #[none] 2 #[none]] = trim/head copy blk - --assert [#[none] 1 #[none] 2] = trim/tail copy blk + --assert [1 #(none) 2 #(none)] = trim/head copy blk + --assert [#(none) 1 #(none) 2] = trim/tail copy blk ;@@ https://github.com/Oldes/Rebol-issues/issues/2482 - --assert [1 #[none] 2] = trim copy blk + --assert [1 #(none) 2] = trim copy blk --assert [1 2] = trim/all copy blk --assert all [error? e: try [trim/head/all []] e/id = 'bad-refines] --assert all [error? e: try [trim/tail/all []] e/id = 'bad-refines] @@ -875,13 +875,13 @@ Rebol [ ===start-group=== "EXTEND" --test-- "extend object!" - --assert all [1 == extend o: object[] 'a 1 o = #[object! [a: 1]]] + --assert all [1 == extend o: object[] 'a 1 o = #(object! [a: 1])] --test-- "extend block!" --assert all [1 == extend b: [] 'a 1 b = [a: 1]] --test-- "extend paren!" --assert all [1 == extend b: quote () 'a 1 b = quote (a: 1)] --test-- "extend map!" - --assert all [1 == extend m: #() 'a 1 m = #(a: 1)] + --assert all [1 == extend m: #[] 'a 1 m = #[a: 1]] ===end-group=== @@ -998,7 +998,7 @@ Rebol [ 3 = indexz? atz s 6 ] --test-- "indexz? on vector" - s: #[u16! 3] + s: #(u16! 3) --assert all [ 0 = indexz? s 1 = indexz? next s @@ -1140,7 +1140,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/1815 --assert all [ b: [1 2 3] - not error? try [poke b 2 #[unset]] + not error? try [poke b 2 #(unset)] unset? pick b 2 unset? b/2 ] @@ -1590,11 +1590,11 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/1766 --assert error? try [sort/compare [1 2 3] func [/local loc-1 loc-2][local < loc-1] ] ;@@ https://github.com/Oldes/Rebol-issues/issues/1516 - --assert error? try [sort/compare [1 2 #[unset]] :>] + --assert error? try [sort/compare [1 2 #(unset)] :>] --test-- "SORT with unset!" ;@@ https://github.com/Oldes/Rebol-issues/issues/1124 - --assert [#[unset] 2 3] = sort reduce [2 #[unset] 3 ] + --assert [#(unset) 2 3] = sort reduce [2 #(unset) 3 ] --test-- "SORT/reverse" ;@@ https://github.com/Oldes/Rebol-issues/issues/128 @@ -1804,7 +1804,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/806 --assert #{0303} = remove-each v #{03010203} [v < 3] - --assert [3 3] = to block! remove-each v #[u16! [3 1 2 3]] [v < 3] + --assert [3 3] = to block! remove-each v #(u16! [3 1 2 3]) [v < 3] --test-- "remove-each/count result" b: [a 1 b 2] @@ -2163,7 +2163,7 @@ Rebol [ append s #"o" --assert f = %hello --assert e = to-email %hello - --assert u = #[url! "hello"] + --assert u = #(url! "hello") --assert t = --assert r = @hello @@ -2185,7 +2185,7 @@ Rebol [ s: "hell" --assert file? f: as %file s --assert email? e: as e@mail s - --assert url? u: as #[url! ""] s + --assert url? u: as #(url! "") s --assert tag? t: as s --assert ref? r: as @ref s @@ -2459,7 +2459,7 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/400 --assert "123" = union "12" "13" --test-- "union with none and unset" - --assert [#[none] #[unset]] = union [#[none]] [#[unset]] + --assert [#(none) #(unset)] = union [#(none)] [#(unset)] --test-- "union/skip" ;@@ https://github.com/Oldes/Rebol-issues/issues/2520 @@ -2532,21 +2532,21 @@ Rebol [ --test-- "unique with unset and none" ;@@ https://github.com/Oldes/Rebol-issues/issues/1124 ;@@ https://github.com/Oldes/Rebol-issues/issues/1592 - --assert [#[unset] #[none]] = unique reduce [unset 'a unset 'a none none] + --assert [#(unset) #(none)] = unique reduce [unset 'a unset 'a none none] ===end-group=== ===start-group=== "INTERSECT" --test-- "intersect" - --assert [#[none] 1 #[unset]] = intersect [#[none] 1 #[unset]] [#[none] #[unset] 1] - --assert [] = intersect [#[none]] [1 #[unset]] + --assert [#(none) 1 #(unset)] = intersect [#(none) 1 #(unset)] [#(none) #(unset) 1] + --assert [] = intersect [#(none)] [1 #(unset)] ===end-group=== ===start-group=== "EXTRACT" --test-- "extract with unset" ;@@ https://github.com/Oldes/Rebol-issues/issues/1540 - --assert [5 1 #[unset]] = extract [5 3 1 #[unset] #[unset] #[unset]] 2 + --assert [5 1 #(unset)] = extract [5 3 1 #(unset) #(unset) #(unset)] 2 ===end-group=== @@ -2603,7 +2603,7 @@ Rebol [ --assert (mold to-path [1 2 3]) = "1/2/3" --assert (mold to-path [1 none 3]) = "1/none/3" ;@@ https://github.com/Oldes/Rebol-issues/issues/477 - --assert path? p: try [to-path b: [1 #[none] #[true] [] () #{}]] + --assert path? p: try [to-path b: [1 #(none) #(true) [] () #{}]] --assert integer? p/1 --assert none? p/2 --assert true? p/3 @@ -2646,7 +2646,7 @@ Rebol [ ===start-group=== "ARRAY" --test-- "array" - --assert [#[none] #[none]] = array 2 + --assert [#(none) #(none)] = array 2 --test-- "array/initial" --assert [0 0] = array/initial 2 0 ;@@ https://github.com/Oldes/Rebol-issues/issues/360 @@ -2722,8 +2722,8 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-wishes/issues/19 --test-- "combine to string" --assert "abc" = combine [a b c] - --assert "abc" = combine [a #[none] b () c #[unset]] - --assert "a|b|c" = combine/with [a #[none] b () c #[unset]] #"|" + --assert "abc" = combine [a #(none) b () c #(unset)] + --assert "a|b|c" = combine/with [a #(none) b () c #(unset)] #"|" --assert "abcghi" = combine [{abc} (if false {def}) {ghi}] --assert "abcghi" = combine reduce [{abc} if false {def} {ghi}] --assert "a, b, c" = combine/with [a b c] ", " @@ -2739,7 +2739,7 @@ Rebol [ --assert %a/1/c = combine/into/with [#"a" 1 "c"] %"" #"/" --test-- "combine to path" - --assert 'a/b/c = combine/into [a b #[none] c] make path! 3 + --assert 'a/b/c = combine/into [a b #(none) c] make path! 3 --test-- "combine to tag" url: http://rebol.com @@ -2766,8 +2766,8 @@ Rebol [ ===start-group=== "COLLECT" --test-- "collect unset" ;@@ https://github.com/Oldes/Rebol-issues/issues/880 - --assert unset? first collect [keep #[unset]] - --assert unset? first head insert copy [] #[unset] + --assert unset? first collect [keep #(unset)] + --assert unset? first head insert copy [] #(unset) ===end-group=== @@ -2836,13 +2836,13 @@ Rebol [ --assert 0 = sum [] --assert 6 = sum [1 2 3] --assert 6.0 = sum [1.0 2 3] - --assert 6 = sum #[uint8! [1 2 3]] + --assert 6 = sum #(uint8! [1 2 3]) --test-- "average" --assert none? average [] --assert 2 = average [1 2 3] --assert 2.0 = average [1.0 2 3] - --assert 2 = average #[uint8! [1 2 3]] - --assert 17.5 = average #[uint8! [10 25]] + --assert 2 = average #(uint8! [1 2 3]) + --assert 17.5 = average #(uint8! [10 25]) ===end-group=== diff --git a/src/tests/units/typeset-test.r3 b/src/tests/units/typeset-test.r3 index a558f5a202..1dd6dcc168 100644 --- a/src/tests/units/typeset-test.r3 +++ b/src/tests/units/typeset-test.r3 @@ -61,9 +61,9 @@ Rebol [ --test-- "issue-985" ;@@ https://github.com/Oldes/Rebol-issues/issues/985 - --assert [#[end!]] = difference system/catalog/datatypes to-block any-type! + --assert [#(end!)] = difference system/catalog/datatypes to-block any-type! --assert (last to-block any-type!) == (last system/catalog/datatypes) - --assert #[typeset! [end!]] = difference make typeset! system/catalog/datatypes any-type! + --assert #(typeset! [end!]) = difference make typeset! system/catalog/datatypes any-type! ===end-group=== diff --git a/src/tests/units/vector-test.r3 b/src/tests/units/vector-test.r3 index f41988efbc..7b6521024a 100644 --- a/src/tests/units/vector-test.r3 +++ b/src/tests/units/vector-test.r3 @@ -57,30 +57,30 @@ Rebol [ --test-- "HEAD, TAIL on vector" ;@@ https://github.com/Oldes/Rebol-issues/issues/462 - v: #[u8! [1 2 3]] + v: #(u8! [1 2 3]) --assert tail? tail v --assert head? head v --test-- "to-block vector!" ;@@ https://github.com/Oldes/Rebol-issues/issues/865 --assert [0 0] = to-block make vector! [integer! 32 2] - --assert [1 2] = to block! #[u16! [1 2]] + --assert [1 2] = to block! #(u16! [1 2]) --test-- "to-binary vector!" ;@@ https://github.com/Oldes/Rebol-issues/issues/2590 - --assert #{01000200} = to binary! #[u16! [1 2]] - --assert #{0100000002000000} = to binary! #[i32! [1 2]] - --assert #{0000803F00000040} = to binary! #[f32! [1 2]] - --assert #{01000000000000000200000000000000} = to binary! #[i64! [1 2]] - --assert #{000000000000F03F0000000000000040} = to binary! #[f64! [1 2]] + --assert #{01000200} = to binary! #(u16! [1 2]) + --assert #{0100000002000000} = to binary! #(i32! [1 2]) + --assert #{0000803F00000040} = to binary! #(f32! [1 2]) + --assert #{01000000000000000200000000000000} = to binary! #(i64! [1 2]) + --assert #{000000000000F03F0000000000000040} = to binary! #(f64! [1 2]) ;@@ https://github.com/Oldes/Rebol-issues/issues/2518 - --assert #{0200} = to binary! next #[u16! [1 2]] - --assert #{02000000} = to binary! next #[i32! [1 2]] - --assert #{00000040} = to binary! next #[f32! [1 2]] - --assert #{0200000000000000} = to binary! next #[i64! [1 2]] - --assert #{0000000000000040} = to binary! next #[f64! [1 2]] + --assert #{0200} = to binary! next #(u16! [1 2]) + --assert #{02000000} = to binary! next #(i32! [1 2]) + --assert #{00000040} = to binary! next #(f32! [1 2]) + --assert #{0200000000000000} = to binary! next #(i64! [1 2]) + --assert #{0000000000000040} = to binary! next #(f64! [1 2]) ;@@ https://github.com/Oldes/Rebol-issues/issues/2458 - --assert #{01000200} = to binary! protect #[u16! [1 2]] + --assert #{01000200} = to binary! protect #(u16! [1 2]) --test-- "LOAD/MOLD on vector" --assert v = load mold/all v @@ -115,7 +115,7 @@ Rebol [ --assert none? v/3 --assert 1 = length? v: make vector! [integer! 16 1 #{01000200}] --assert none? v/2 - --assert 1 = length? v: #[i16! 1 #{01000200}] + --assert 1 = length? v: #(i16! 1 #{01000200}) --assert none? v/2 --test-- "Extending input specification when size and series is provided" @@ -128,8 +128,8 @@ Rebol [ ;@@ https://github.com/Oldes/Rebol-issues/issues/1038 --assert 2 = index? v: make vector! [integer! 16 [1 2] 2] --assert 2 = index? v: make vector! [integer! 16 #{01000200} 2] - --assert 2 = index? v: #[i16! [1 2] 2] - --assert 2 = index? v: #[i16! #{01000200} 2] + --assert 2 = index? v: #(i16! [1 2] 2) + --assert 2 = index? v: #(i16! #{01000200} 2) --test-- "MOLD of unsigned vector" ;@@ https://github.com/Oldes/Rebol-issues/issues/756 @@ -139,7 +139,7 @@ Rebol [ --test-- "MOLD/flat on vector" ;@@ https://github.com/Oldes/Rebol-issues/issues/2349 --assert (mold/flat make vector! [integer! 8 12]) = {make vector! [integer! 8 12 [0 0 0 0 0 0 0 0 0 0 0 0]]} - --assert (mold/all/flat make vector! [integer! 8 12]) = "#[vector! integer! 8 12 [0 0 0 0 0 0 0 0 0 0 0 0]]" + --assert (mold/all/flat make vector! [integer! 8 12]) = "#(vector! integer! 8 12 [0 0 0 0 0 0 0 0 0 0 0 0])" --assert (mold make vector! [integer! 8 2]) = {make vector! [integer! 8 2 [0 0]]} --assert (mold make vector! [integer! 8 20]) = {make vector! [integer! 8 20 [ 0 0 0 0 0 0 0 0 0 0 @@ -189,98 +189,98 @@ Rebol [ --test-- "REVERSE on vector" ;@@ https://github.com/Oldes/Rebol-issues/issues/2515 - --assert #[u8! [3 2 1]] = reverse #[u8! [1 2 3]] - --assert #[u16! [3 2 1]] = reverse #[u16! [1 2 3]] - --assert #[u32! [3 2 1]] = reverse #[u32! [1 2 3]] - --assert #[u64! [3 2 1]] = reverse #[u64! [1 2 3]] - --assert #[i8! [3 2 1]] = reverse #[i8! [1 2 3]] - --assert #[i16! [3 2 1]] = reverse #[i16! [1 2 3]] - --assert #[i32! [3 2 1]] = reverse #[i32! [1 2 3]] - --assert #[i64! [3 2 1]] = reverse #[i64! [1 2 3]] - --assert #[f32! [3.0 2.0 1.0]] = reverse #[f32! [1 2 3]] - --assert #[f64! [3.0 2.0 1.0]] = reverse #[f64! [1 2 3]] - - --assert #[u8! [2 1 3]] = reverse/part #[u8! [1 2 3]] 2 - --assert #[u16! [2 1 3]] = reverse/part #[u16! [1 2 3]] 2 - --assert #[u32! [2 1 3]] = reverse/part #[u32! [1 2 3]] 2 - --assert #[u64! [2 1 3]] = reverse/part #[u64! [1 2 3]] 2 - --assert #[i8! [2 1 3]] = reverse/part #[i8! [1 2 3]] 2 - --assert #[i16! [2 1 3]] = reverse/part #[i16! [1 2 3]] 2 - --assert #[i32! [2 1 3]] = reverse/part #[i32! [1 2 3]] 2 - --assert #[i64! [2 1 3]] = reverse/part #[i64! [1 2 3]] 2 - --assert #[f32! [2.0 1.0 3.0]] = reverse/part #[f32! [1 2 3]] 2 - --assert #[f64! [2.0 1.0 3.0]] = reverse/part #[f64! [1 2 3]] 2 - - --assert #[u8! [1 3 2]] = head reverse next #[u8! [1 2 3]] - --assert #[u16! [1 3 2]] = head reverse next #[u16! [1 2 3]] - --assert #[u32! [1 3 2]] = head reverse next #[u32! [1 2 3]] - --assert #[u64! [1 3 2]] = head reverse next #[u64! [1 2 3]] - --assert #[i8! [1 3 2]] = head reverse next #[i8! [1 2 3]] - --assert #[i16! [1 3 2]] = head reverse next #[i16! [1 2 3]] - --assert #[i32! [1 3 2]] = head reverse next #[i32! [1 2 3]] - --assert #[i64! [1 3 2]] = head reverse next #[i64! [1 2 3]] - --assert #[f32! [1.0 3.0 2.0]] = head reverse next #[f32! [1 2 3]] - --assert #[f64! [1.0 3.0 2.0]] = head reverse next #[f64! [1 2 3]] + --assert #(u8! [3 2 1]) = reverse #(u8! [1 2 3]) + --assert #(u16! [3 2 1]) = reverse #(u16! [1 2 3]) + --assert #(u32! [3 2 1]) = reverse #(u32! [1 2 3]) + --assert #(u64! [3 2 1]) = reverse #(u64! [1 2 3]) + --assert #(i8! [3 2 1]) = reverse #(i8! [1 2 3]) + --assert #(i16! [3 2 1]) = reverse #(i16! [1 2 3]) + --assert #(i32! [3 2 1]) = reverse #(i32! [1 2 3]) + --assert #(i64! [3 2 1]) = reverse #(i64! [1 2 3]) + --assert #(f32! [3.0 2.0 1.0]) = reverse #(f32! [1 2 3]) + --assert #(f64! [3.0 2.0 1.0]) = reverse #(f64! [1 2 3]) + + --assert #(u8! [2 1 3]) = reverse/part #(u8! [1 2 3]) 2 + --assert #(u16! [2 1 3]) = reverse/part #(u16! [1 2 3]) 2 + --assert #(u32! [2 1 3]) = reverse/part #(u32! [1 2 3]) 2 + --assert #(u64! [2 1 3]) = reverse/part #(u64! [1 2 3]) 2 + --assert #(i8! [2 1 3]) = reverse/part #(i8! [1 2 3]) 2 + --assert #(i16! [2 1 3]) = reverse/part #(i16! [1 2 3]) 2 + --assert #(i32! [2 1 3]) = reverse/part #(i32! [1 2 3]) 2 + --assert #(i64! [2 1 3]) = reverse/part #(i64! [1 2 3]) 2 + --assert #(f32! [2.0 1.0 3.0]) = reverse/part #(f32! [1 2 3]) 2 + --assert #(f64! [2.0 1.0 3.0]) = reverse/part #(f64! [1 2 3]) 2 + + --assert #(u8! [1 3 2]) = head reverse next #(u8! [1 2 3]) + --assert #(u16! [1 3 2]) = head reverse next #(u16! [1 2 3]) + --assert #(u32! [1 3 2]) = head reverse next #(u32! [1 2 3]) + --assert #(u64! [1 3 2]) = head reverse next #(u64! [1 2 3]) + --assert #(i8! [1 3 2]) = head reverse next #(i8! [1 2 3]) + --assert #(i16! [1 3 2]) = head reverse next #(i16! [1 2 3]) + --assert #(i32! [1 3 2]) = head reverse next #(i32! [1 2 3]) + --assert #(i64! [1 3 2]) = head reverse next #(i64! [1 2 3]) + --assert #(f32! [1.0 3.0 2.0]) = head reverse next #(f32! [1 2 3]) + --assert #(f64! [1.0 3.0 2.0]) = head reverse next #(f64! [1 2 3]) ===end-group=== ===start-group=== "VECTOR compact construction" ;@@ https://github.com/Oldes/Rebol-issues/issues/2396 --test-- "Compact construction syntax (empty)" - --assert (mold #[i8! ]) = "make vector! [integer! 8 0 []]" - --assert (mold #[i16!]) = "make vector! [integer! 16 0 []]" - --assert (mold #[i32!]) = "make vector! [integer! 32 0 []]" - --assert (mold #[i64!]) = "make vector! [integer! 64 0 []]" - --assert (mold #[u8! ]) = "make vector! [unsigned integer! 8 0 []]" - --assert (mold #[u16!]) = "make vector! [unsigned integer! 16 0 []]" - --assert (mold #[u32!]) = "make vector! [unsigned integer! 32 0 []]" - --assert (mold #[u64!]) = "make vector! [unsigned integer! 64 0 []]" - --assert (mold #[f32! ]) = "make vector! [decimal! 32 0 []]" - --assert (mold #[f64! ]) = "make vector! [decimal! 64 0 []]" + --assert (mold #(i8! )) = "make vector! [integer! 8 0 []]" + --assert (mold #(i16!)) = "make vector! [integer! 16 0 []]" + --assert (mold #(i32!)) = "make vector! [integer! 32 0 []]" + --assert (mold #(i64!)) = "make vector! [integer! 64 0 []]" + --assert (mold #(u8! )) = "make vector! [unsigned integer! 8 0 []]" + --assert (mold #(u16!)) = "make vector! [unsigned integer! 16 0 []]" + --assert (mold #(u32!)) = "make vector! [unsigned integer! 32 0 []]" + --assert (mold #(u64!)) = "make vector! [unsigned integer! 64 0 []]" + --assert (mold #(f32! )) = "make vector! [decimal! 32 0 []]" + --assert (mold #(f64! )) = "make vector! [decimal! 64 0 []]" --test-- "Compact construction syntax (size)" - --assert (mold #[i8! 3]) = "make vector! [integer! 8 3 [0 0 0]]" - --assert (mold #[i16! 3]) = "make vector! [integer! 16 3 [0 0 0]]" - --assert (mold #[i32! 3]) = "make vector! [integer! 32 3 [0 0 0]]" - --assert (mold #[i64! 3]) = "make vector! [integer! 64 3 [0 0 0]]" - --assert (mold #[u8! 3]) = "make vector! [unsigned integer! 8 3 [0 0 0]]" - --assert (mold #[u16! 3]) = "make vector! [unsigned integer! 16 3 [0 0 0]]" - --assert (mold #[u32! 3]) = "make vector! [unsigned integer! 32 3 [0 0 0]]" - --assert (mold #[u64! 3]) = "make vector! [unsigned integer! 64 3 [0 0 0]]" - --assert (mold #[f32! 3]) = "make vector! [decimal! 32 3 [0.0 0.0 0.0]]" - --assert (mold #[f64! 3]) = "make vector! [decimal! 64 3 [0.0 0.0 0.0]]" + --assert (mold #(i8! 3)) = "make vector! [integer! 8 3 [0 0 0]]" + --assert (mold #(i16! 3)) = "make vector! [integer! 16 3 [0 0 0]]" + --assert (mold #(i32! 3)) = "make vector! [integer! 32 3 [0 0 0]]" + --assert (mold #(i64! 3)) = "make vector! [integer! 64 3 [0 0 0]]" + --assert (mold #(u8! 3)) = "make vector! [unsigned integer! 8 3 [0 0 0]]" + --assert (mold #(u16! 3)) = "make vector! [unsigned integer! 16 3 [0 0 0]]" + --assert (mold #(u32! 3)) = "make vector! [unsigned integer! 32 3 [0 0 0]]" + --assert (mold #(u64! 3)) = "make vector! [unsigned integer! 64 3 [0 0 0]]" + --assert (mold #(f32! 3)) = "make vector! [decimal! 32 3 [0.0 0.0 0.0]]" + --assert (mold #(f64! 3)) = "make vector! [decimal! 64 3 [0.0 0.0 0.0]]" --test-- "Compact construction syntax (data)" - --assert (mold #[i8! [1 2]]) = "make vector! [integer! 8 2 [1 2]]" - --assert (mold #[i16! [1 2]]) = "make vector! [integer! 16 2 [1 2]]" - --assert (mold #[i32! [1 2]]) = "make vector! [integer! 32 2 [1 2]]" - --assert (mold #[i64! [1 2]]) = "make vector! [integer! 64 2 [1 2]]" - --assert (mold #[u8! [1 2]]) = "make vector! [unsigned integer! 8 2 [1 2]]" - --assert (mold #[u16! [1 2]]) = "make vector! [unsigned integer! 16 2 [1 2]]" - --assert (mold #[u32! [1 2]]) = "make vector! [unsigned integer! 32 2 [1 2]]" - --assert (mold #[u64! [1 2]]) = "make vector! [unsigned integer! 64 2 [1 2]]" - --assert (mold #[f32! [1 2]]) = "make vector! [decimal! 32 2 [1.0 2.0]]" - --assert (mold #[f64! [1 2]]) = "make vector! [decimal! 64 2 [1.0 2.0]]" + --assert (mold #(i8! [1 2])) = "make vector! [integer! 8 2 [1 2]]" + --assert (mold #(i16! [1 2])) = "make vector! [integer! 16 2 [1 2]]" + --assert (mold #(i32! [1 2])) = "make vector! [integer! 32 2 [1 2]]" + --assert (mold #(i64! [1 2])) = "make vector! [integer! 64 2 [1 2]]" + --assert (mold #(u8! [1 2])) = "make vector! [unsigned integer! 8 2 [1 2]]" + --assert (mold #(u16! [1 2])) = "make vector! [unsigned integer! 16 2 [1 2]]" + --assert (mold #(u32! [1 2])) = "make vector! [unsigned integer! 32 2 [1 2]]" + --assert (mold #(u64! [1 2])) = "make vector! [unsigned integer! 64 2 [1 2]]" + --assert (mold #(f32! [1 2])) = "make vector! [decimal! 32 2 [1.0 2.0]]" + --assert (mold #(f64! [1 2])) = "make vector! [decimal! 64 2 [1.0 2.0]]" --test-- "Compact construction syntax (data with index)" - --assert (mold v: #[i8! [1 2] 2]) = "make vector! [integer! 8 1 [2]]" + --assert (mold v: #(i8! [1 2] 2)) = "make vector! [integer! 8 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i16! [1 2] 2]) = "make vector! [integer! 16 1 [2]]" + --assert (mold v: #(i16! [1 2] 2)) = "make vector! [integer! 16 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i32! [1 2] 2]) = "make vector! [integer! 32 1 [2]]" + --assert (mold v: #(i32! [1 2] 2)) = "make vector! [integer! 32 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i64! [1 2] 2]) = "make vector! [integer! 64 1 [2]]" + --assert (mold v: #(i64! [1 2] 2)) = "make vector! [integer! 64 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u8! [1 2] 2]) = "make vector! [unsigned integer! 8 1 [2]]" + --assert (mold v: #(u8! [1 2] 2)) = "make vector! [unsigned integer! 8 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u16! [1 2] 2]) = "make vector! [unsigned integer! 16 1 [2]]" + --assert (mold v: #(u16! [1 2] 2)) = "make vector! [unsigned integer! 16 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u32! [1 2] 2]) = "make vector! [unsigned integer! 32 1 [2]]" + --assert (mold v: #(u32! [1 2] 2)) = "make vector! [unsigned integer! 32 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u64! [1 2] 2]) = "make vector! [unsigned integer! 64 1 [2]]" + --assert (mold v: #(u64! [1 2] 2)) = "make vector! [unsigned integer! 64 1 [2]]" --assert 2 = index? v - --assert (mold v: #[f32! [1 2] 2]) = "make vector! [decimal! 32 1 [2.0]]" + --assert (mold v: #(f32! [1 2] 2)) = "make vector! [decimal! 32 1 [2.0]]" --assert 2 = index? v - --assert (mold v: #[f64! [1 2] 2]) = "make vector! [decimal! 64 1 [2.0]]" + --assert (mold v: #(f64! [1 2] 2)) = "make vector! [decimal! 64 1 [2.0]]" --assert 2 = index? v ===end-group=== @@ -358,107 +358,107 @@ Rebol [ --assert 2 = index? v --test-- "Construction syntax" - --assert (mold v: #[i8! [1 2] 2]) = "make vector! [integer! 8 1 [2]]" + --assert (mold v: #(i8! [1 2] 2)) = "make vector! [integer! 8 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i16! [1 2] 2]) = "make vector! [integer! 16 1 [2]]" + --assert (mold v: #(i16! [1 2] 2)) = "make vector! [integer! 16 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i32! [1 2] 2]) = "make vector! [integer! 32 1 [2]]" + --assert (mold v: #(i32! [1 2] 2)) = "make vector! [integer! 32 1 [2]]" --assert 2 = index? v - --assert (mold v: #[i64! [1 2] 2]) = "make vector! [integer! 64 1 [2]]" + --assert (mold v: #(i64! [1 2] 2)) = "make vector! [integer! 64 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u8! [1 2] 2]) = "make vector! [unsigned integer! 8 1 [2]]" + --assert (mold v: #(u8! [1 2] 2)) = "make vector! [unsigned integer! 8 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u16! [1 2] 2]) = "make vector! [unsigned integer! 16 1 [2]]" + --assert (mold v: #(u16! [1 2] 2)) = "make vector! [unsigned integer! 16 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u32! [1 2] 2]) = "make vector! [unsigned integer! 32 1 [2]]" + --assert (mold v: #(u32! [1 2] 2)) = "make vector! [unsigned integer! 32 1 [2]]" --assert 2 = index? v - --assert (mold v: #[u64! [1 2] 2]) = "make vector! [unsigned integer! 64 1 [2]]" + --assert (mold v: #(u64! [1 2] 2)) = "make vector! [unsigned integer! 64 1 [2]]" --assert 2 = index? v - --assert (mold v: #[f32! [1 2] 2]) = "make vector! [decimal! 32 1 [2.0]]" + --assert (mold v: #(f32! [1 2] 2)) = "make vector! [decimal! 32 1 [2.0]]" --assert 2 = index? v - --assert (mold v: #[f64! [1 2] 2]) = "make vector! [decimal! 64 1 [2.0]]" + --assert (mold v: #(f64! [1 2] 2)) = "make vector! [decimal! 64 1 [2.0]]" --assert 2 = index? v ===end-group=== ===start-group=== "VECTOR math" --test-- "VECTOR 8bit integer add/subtract" - v: #[u8![1 2 3 4]] - --assert (v + 200) = #[u8![201 202 203 204]] + v: #(u8![1 2 3 4]) + --assert (v + 200) = #(u8![201 202 203 204]) ; the values are truncated on overflow: - --assert (v + 200) = #[u8![145 146 147 148]] - --assert (v - 400) = #[u8![1 2 3 4]] + --assert (v + 200) = #(u8![145 146 147 148]) + --assert (v - 400) = #(u8![1 2 3 4]) subtract (add v 10) 10 - --assert v = #[u8![1 2 3 4]] + --assert v = #(u8![1 2 3 4]) 1 + v - --assert v = #[u8![2 3 4 5]] + --assert v = #(u8![2 3 4 5]) -1.0 + v - --assert v = #[u8![1 2 3 4]] + --assert v = #(u8![1 2 3 4]) - v: #[i8![1 2 3 4]] - --assert (v + 125) = #[i8![126 127 -128 -127]] - --assert (v - 125) = #[i8![1 2 3 4]] + v: #(i8![1 2 3 4]) + --assert (v + 125) = #(i8![126 127 -128 -127]) + --assert (v - 125) = #(i8![1 2 3 4]) --test-- "VECTOR 8bit integer multiply" - v: #[u8![1 2 3 4]] - --assert (v * 4) = #[u8![4 8 12 16]] + v: #(u8![1 2 3 4]) + --assert (v * 4) = #(u8![4 8 12 16]) ; the values are truncated on overflow: - --assert (v * 20) = #[u8![80 160 240 64]] ;64 = (16 * 20) - 256 + --assert (v * 20) = #(u8![80 160 240 64]) ;64 = (16 * 20) - 256 - v: #[i8![1 2 3 4]] - --assert (v * 2.0) = #[i8![2 4 6 8]] + v: #(i8![1 2 3 4]) + --assert (v * 2.0) = #(i8![2 4 6 8]) ; the decimal is first converted to integer (2): - --assert (v * 2.4) = #[i8![4 8 12 16]] + --assert (v * 2.4) = #(i8![4 8 12 16]) subtract (add v 10) 10 - --assert v = #[i8![4 8 12 16]] + --assert v = #(i8![4 8 12 16]) --test-- "VECTOR 16bit integer multiply" - v: #[u16![1 2 3 4]] - --assert (v * 4) = #[u16![4 8 12 16]] - --assert (v * 20) = #[u16![80 160 240 320]] + v: #(u16![1 2 3 4]) + --assert (v * 4) = #(u16![4 8 12 16]) + --assert (v * 20) = #(u16![80 160 240 320]) multiply v 2 - --assert v = #[u16![160 320 480 640]] + --assert v = #(u16![160 320 480 640]) - v: #[u16![1 2 3 4]] - --assert (10 * copy v) = #[u16![10 20 30 40]] - --assert (10.0 * copy v) = #[u16![10 20 30 40]] + v: #(u16![1 2 3 4]) + --assert (10 * copy v) = #(u16![10 20 30 40]) + --assert (10.0 * copy v) = #(u16![10 20 30 40]) ; the values are truncated on overflow: - v: #[u16![1 2 3 4]] - --assert (v * 10000) = #[u16![10000 20000 30000 40000]] - --assert (v * 10.0) = #[u16![34464 3392 37856 6784]] + v: #(u16![1 2 3 4]) + --assert (v * 10000) = #(u16![10000 20000 30000 40000]) + --assert (v * 10.0) = #(u16![34464 3392 37856 6784]) --test-- "VECTOR 16bit integer divide" - v: #[u16![80 160 240 320]] + v: #(u16![80 160 240 320]) v / 20 / 2 divide v 2 - --assert v = #[u16![1 2 3 4]] + --assert v = #(u16![1 2 3 4]) --assert error? try [10 / v] --assert error? try [ v / 0] --test-- "VECTOR 32bit decimal add/subtract" - v: #[f32![1 2 3 4]] - --assert (v + 200) = #[f32![201 202 203 204]] - --assert (v + 0.5) = #[f32![201.5 202.5 203.5 204.5]] + v: #(f32![1 2 3 4]) + --assert (v + 200) = #(f32![201 202 203 204]) + --assert (v + 0.5) = #(f32![201.5 202.5 203.5 204.5]) ; notice the precision lost with 32bit decimal value: v - 0.1 --assert 2013 = to integer! 10 * v/1 ; result is not 201.4 as would be with 64bit --test-- "VECTOR 64bit decimal add/subtract" - v: #[f64![1 2 3 4]] - --assert (v + 200) = #[f64![201 202 203 204]] - --assert (v + 0.5) = #[f64![201.5 202.5 203.5 204.5]] - --assert (v - 0.1) = #[f64![201.4 202.4 203.4 204.4]] + v: #(f64![1 2 3 4]) + --assert (v + 200) = #(f64![201 202 203 204]) + --assert (v + 0.5) = #(f64![201.5 202.5 203.5 204.5]) + --assert (v - 0.1) = #(f64![201.4 202.4 203.4 204.4]) --test-- "VECTOR 64bit decimal multiply/divide" - v: #[f64![1 2 3 4]] - --assert (v * 20.5) = #[f64![20.5 41.0 61.5 82.0]] - --assert (v / 20.5) = #[f64![1.0 2.0 3.0 4.0]] + v: #(f64![1 2 3 4]) + --assert (v * 20.5) = #(f64![20.5 41.0 61.5 82.0]) + --assert (v / 20.5) = #(f64![1.0 2.0 3.0 4.0]) --test-- "VECTOR math operation with vector not at head" - v: #[i8![1 2 3 4]] - --assert (2 + skip v 2) = #[i8![5 6]] - --assert v = #[i8![1 2 5 6]] + v: #(i8![1 2 3 4]) + --assert (2 + skip v 2) = #(i8![5 6]) + --assert v = #(i8![1 2 5 6]) ===end-group=== @@ -467,12 +467,12 @@ Rebol [ --test-- "compare vectors" ;@@ https://github.com/Oldes/Rebol-issues/issues/458 --assert equal? (make vector! 3)(make vector! 3) - --assert not equal? #[u16! [1 2]] #[u16! [1 2 3]] - --assert #[u16! [1 2]] = #[u16! [1 2]] - --assert #[u16! [1 2]] < #[u16! [1 2 0]] - --assert #[u16! [1 2]] < #[u16! [1 2 1]] - --assert #[u16! [1 2]] < #[u16! [2 2]] - --assert #[u16! [2 2]] > #[u16! [1 2]] + --assert not equal? #(u16! [1 2]) #(u16! [1 2 3]) + --assert #(u16! [1 2]) = #(u16! [1 2]) + --assert #(u16! [1 2]) < #(u16! [1 2 0]) + --assert #(u16! [1 2]) < #(u16! [1 2 1]) + --assert #(u16! [1 2]) < #(u16! [2 2]) + --assert #(u16! [2 2]) > #(u16! [1 2]) ===end-group=== @@ -482,7 +482,7 @@ Rebol [ --test-- "COPY" ;@@ https://github.com/Oldes/Rebol-issues/issues/463 ;@@ https://github.com/Oldes/Rebol-issues/issues/2400 - v1: #[u16! [1 2]] + v1: #(u16! [1 2]) v2: v1 v3: copy v2 --assert same? v1 v2 @@ -494,7 +494,7 @@ Rebol [ --test-- "COPY/PART" ;@@ https://github.com/Oldes/Rebol-issues/issues/2399 - v: #[u16! [1 2 3 4]] + v: #(u16! [1 2 3 4]) --assert 2 = length? copy/part v 2 --assert #{01000200} = to-binary copy/part v 2 --assert #{03000400} = to-binary copy/part skip v 2 2 @@ -505,7 +505,7 @@ Rebol [ ===start-group=== "PICK" --test-- "PICK of vector!" ;@@ https://github.com/Oldes/Rebol-issues/issues/748 - v: #[u32! [1 2 3]] + v: #(u32! [1 2 3]) --assert all [ 1 = pick v 1 2 = pick v 2 @@ -518,7 +518,7 @@ Rebol [ ===start-group=== "POKE" --test-- "POKE into vector!" - v: #[u32! [1 2 3]] + v: #(u32! [1 2 3]) --assert all [ 10 = poke v 1 10 10 = pick v 1 @@ -546,7 +546,7 @@ Rebol [ ===start-group=== "FIND-MAX / FIND-MIN" ;@@ https://github.com/Oldes/Rebol-issues/issues/460 - v: #[i32! [1 2 3 -1]] + v: #(i32! [1 2 3 -1]) --test-- "FIND-MAX vector!" --assert 3 = first find-max v --test-- "FIND-MIN vector!" --assert -1 = first find-min v ===end-group=== From bea5d79ad3e628e076cff4d0e522df471afebeba Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Sat, 17 Feb 2024 14:03:24 +0100 Subject: [PATCH 60/60] Updated CHANGES.md --- CHANGES.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 3a68306dd1..91f8ab937e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,10 +2,84 @@ This is just generated output from commits in [this repository](https://github.com/Oldes/Rebol3). For full log use [GitHub commits](https://github.com/Oldes/Rebol3/commits/master). + +## 2024 February + +### Features: + +* [`f25ddf`](https://github.com/Oldes/Rebol3/commit/f25ddfa9239befaab611b209d5b64146b61b75a1) Implemented optional `XXH3`, `XXH32`, `XXH64` and `XXH128` checksums +* [`ab42ca`](https://github.com/Oldes/Rebol3/commit/ab42ca5231abdbc73f11ece0bc8b0dd6953f553b) Tiny optimization +* [`da4718`](https://github.com/Oldes/Rebol3/commit/da4718b39c376b323799ecabe1491fae899ad036) Not using hashing for small enough maps (reduces memory usage) + +### Changes: + +* [`3c2b93`](https://github.com/Oldes/Rebol3/commit/3c2b93afa872334effe9c840813ed789ce1dbd0c) **Switching map and construction syntax** + + `map!` values now use syntax like: `#[key: value]` + construction syntax now looks like: `#(true)` or `#(i32! [1 2 3])` + + The included [`map-conv.reb` script](https://github.com/Oldes/Rebol3/blob/master/make/tools/map-conv.reb) can be used for converting existing code. + +* [`2ba01e`](https://github.com/Oldes/Rebol3/commit/2ba01ead3b5da1ab609fa25a0c675b30e96bb163) `unset` value in `any` and `all` is transparent now + + +### Fixes: + +* [`01a68c`](https://github.com/Oldes/Rebol3/commit/01a68cfbedebd86fda68ce287efba85a0f199660) Compiler warnings +* [`695636`](https://github.com/Oldes/Rebol3/commit/695636065bb7876478dbf70e7f5f4560eb986370) Correct fix of regression when creating 64 bit vectors +* [`238ecb`](https://github.com/Oldes/Rebol3/commit/238ecbcedda7b583ce0d96d4c111dc5d6d1bd330) Regression when creating 64 bit vectors +* [`820687`](https://github.com/Oldes/Rebol3/commit/8206872e89a080622b1d6dc15abfd746aa4d1de8) `checksum` with `file!` argument not supporting all available methods +* [`d4364d`](https://github.com/Oldes/Rebol3/commit/d4364df0e4f48944cb36beba1fdbc32d6d109e9f) Saving a file into a zip archive + +## 2024 January + +### Features: + +* [`e401ed`](https://github.com/Oldes/Rebol3/commit/e401eddfb87ed47243984392bb445409b6fc390a) Added `sum` and `average` functions +* [`27611e`](https://github.com/Oldes/Rebol3/commit/27611e9d02764593484a1c8c9aac151c907145cc) Including source of `webdriver` and `websocket` modules + +### Changes: + +* [`da1905`](https://github.com/Oldes/Rebol3/commit/da1905820e0091c4e27a7746e66f3ca5877a4ca7) Updated Mbed-TLS sources to version 3.5.2 +* [`52efc0`](https://github.com/Oldes/Rebol3/commit/52efc0caca758dfa9fc74256ee26757738c4c115) Register `.swc` file extension with `zip` codec +* [`7c84b6`](https://github.com/Oldes/Rebol3/commit/7c84b60c8a2ba2cbd9c57fb416d87a563ad82713) Allow issues like `###` or `#a#` (Rebol2/Red compatibility) +* [`9bb910`](https://github.com/Oldes/Rebol3/commit/9bb91086c266e190121c075b0b412c29e9c06651) Zlib source updated to version 1.3.0.1 + +### Fixes: + +* [`1bfcbb`](https://github.com/Oldes/Rebol3/commit/1bfcbbcf83827b846ef7f3fa508bd1afc0796de6) Bbcode codec - reset row-width of an image gallery tag +* [`307b24`](https://github.com/Oldes/Rebol3/commit/307b24a9012fdbb37d1d3e29031e7e96ca7dca2d) Windows JPEG codec unexpected property type error +* [`592454`](https://github.com/Oldes/Rebol3/commit/592454e4090018accedbc4730dc79b7cc7320992) LF to CRLF conversion when using `write` with `string` input +* [`fbad12`](https://github.com/Oldes/Rebol3/commit/fbad12f1a426e2802ac16898a88cff287270101b) Joining path/url using path notation not respecting index position +* [`aa7aa4`](https://github.com/Oldes/Rebol3/commit/aa7aa41114ba158d9e55fd3e291099229e3d15fb) Throw an error when converting `1.#NaN` value to integer +* [`45b358`](https://github.com/Oldes/Rebol3/commit/45b358f075215b19490104891c2d8f64a578628e) Close `httpd` server on request even when there are pending client connections + +## 2023 December + +### Features: + +* [`ffa41e`](https://github.com/Oldes/Rebol3/commit/ffa41e0b0d48cc5371e32215c35b3a2d73d47149) `bbcode` image gallery emitter +* [`e39581`](https://github.com/Oldes/Rebol3/commit/e39581578b98b3eeb121f47e99224e8dda2be424) `bbcode` csv table emitter + +### Changes: + +* [`7a9e11`](https://github.com/Oldes/Rebol3/commit/7a9e11000d4275e95940116593ec0a731289d5e0) Updated `httpd` scheme to version 0.9.0 + +### Fixes: + +* [`9715d1`](https://github.com/Oldes/Rebol3/commit/9715d1205bc45b0c195f4ab95f1cdd8c151abe43) Code simplified +* [`aa227f`](https://github.com/Oldes/Rebol3/commit/aa227fc7f8a5571ca3307255a93f0804a174c5b1) Avoid an error when loading an unset value +* [`051670`](https://github.com/Oldes/Rebol3/commit/051670ad6e5b2ec6cee6e95c002a43a06f128a97) Using correct path to images in the generated `bbcode` image gallery +* [`8ee972`](https://github.com/Oldes/Rebol3/commit/8ee972c64ef81df1f58e42e31d7876c6635a8c2a) `bbcode` codec must convert binary input to string before decoding +* [`b0f684`](https://github.com/Oldes/Rebol3/commit/b0f6840ceb23f0f7752f9f7edae25edaced34bbe) Reading from virtual `/proc` files on Linux using `read/part` + ## 2023 November ### Features: +* [`963d08`](https://github.com/Oldes/Rebol3/commit/963d083a5e7fbf2c96ef9a60be386af7ff4402c0) Allow `word!`, `get-word!` and `get-path!` values inside a `call` argument +* [`39c7e2`](https://github.com/Oldes/Rebol3/commit/39c7e22efb9237a1e86e72973ebf0582d3d5e981) Allow any-string value as a `call` argument +* [`a38e2a`](https://github.com/Oldes/Rebol3/commit/a38e2a5c5622641df7ca291a396d4937f871e589) Added possibility to set/clear BRK, RTS and DTR serial port flags on Posix * [`1ff2d9`](https://github.com/Oldes/Rebol3/commit/1ff2d94d69bce3dfb6a55091b246689b8c8e987a) Optional support for SHA3 family checksums (included in Bulk) * [`3dc6f6`](https://github.com/Oldes/Rebol3/commit/3dc6f6aa27408ef814cc90897dedb751eacda703) New platform for TurrisOS * [`feaaef`](https://github.com/Oldes/Rebol3/commit/feaaef940490166984aaff4c9a654324703fbc4b) Better info when native extension fails to load its library @@ -17,6 +91,8 @@ This is just generated output from commits in [this repository](https://github.c ### Changes: +* [`bf4999`](https://github.com/Oldes/Rebol3/commit/bf49996cccaec38302cd6481856bc63dd0ed6bb4) Modified `launch` function not to use shell and to handle all optional script arguments +* [`abc6ec`](https://github.com/Oldes/Rebol3/commit/abc6ecc0b2f6a52a5fdc8724d9c5483f7d9a0757) Using system error codes when opening a MIDI device on Windows * [`35c1b6`](https://github.com/Oldes/Rebol3/commit/35c1b610e7d1a6df74437ee3a2918ff96577a3b0) Updated Mbed-TLS sources to version 3.5.1 * [`4dc546`](https://github.com/Oldes/Rebol3/commit/4dc546e52076f3e88064ccf99039f1a0c00d7cd1) Using line breaks in molded `struct!` values for better readability * [`68bf82`](https://github.com/Oldes/Rebol3/commit/68bf82e5d71403b5345611219c40b5293573557e) Moved `STATIC_ASSERT` macro to `reb-c.h` file and used it in a few more cases @@ -24,6 +100,14 @@ This is just generated output from commits in [this repository](https://github.c ### Fixes: +* [`a73014`](https://github.com/Oldes/Rebol3/commit/a730144ae9cb4d607d6725c5ea0044760e335c08) Accept block input to `call` function on Windows +* [`56a39e`](https://github.com/Oldes/Rebol3/commit/56a39e6267e828add4be1e5d2d1741a452b45128) Warning: implicit declaration of function ‘wcwidth’ +* [`2ea23b`](https://github.com/Oldes/Rebol3/commit/2ea23b1a25f076acaa3f0bdd662ffed58c869de6) Ignore warning: ‘__builtin___strncpy_chk’ specified bound depends on the length of the source argument +* [`a84671`](https://github.com/Oldes/Rebol3/commit/a84671a2d4477e51649884020e4e0993b438a003) Warning: ignoring return value of ‘read’, declared with attribute warn_unused_result +* [`98c54f`](https://github.com/Oldes/Rebol3/commit/98c54fc5eac64ce2b717c39660faca77f90a1a9a) Warning: specified bound depends on the length of the source argument +* [`45832b`](https://github.com/Oldes/Rebol3/commit/45832b91fbf9c82907ecb6806ebeee7a42e00e17) Trying to fix build for Haiku OS +* [`da13e8`](https://github.com/Oldes/Rebol3/commit/da13e819a8cf94f79dd40a26523ecb5b219295d4) Trying to fix build for Haiku OS +* [`7f8108`](https://github.com/Oldes/Rebol3/commit/7f81085e563a65e2e71e0ee326e56c081ef98d66) Trying to fix build for Haiku OS * [`0be75d`](https://github.com/Oldes/Rebol3/commit/0be75dc3a360f2eaab92debb06605f1a2287ef76) Timeout when reading some HTTPS URLs * [`b63745`](https://github.com/Oldes/Rebol3/commit/b63745d321ba99b8d9392341e909c9ec47b8a9e2) Invalid length of `checksum:sha224` port result * [`a87e66`](https://github.com/Oldes/Rebol3/commit/a87e667ab9e195a7d4becf4df14a411ef16ed551) Redundant message when logging an error value